int mp_snmp_values_fetch1(netsnmp_session *ss, const mp_snmp_query_cmd *values) { netsnmp_pdu *request; netsnmp_pdu *response; const netsnmp_variable_list *var; const mp_snmp_query_cmd *vp; int rc; /* * set-up request */ request = snmp_pdu_create(SNMP_MSG_GET); for (vp = values; vp->oid_len && vp->oid; vp++) { snmp_add_null_var(request, vp->oid, vp->oid_len); } /* * commence request */ do { rc = snmp_synch_response(ss, request, &response); if (mp_verbose > 3) printf("snmp_synch_response(): rc=%d\n", rc); /* no result, so something went wrong ... */ if (!response) return STAT_ERROR; if ((rc == STAT_SUCCESS) && (response->errindex == 0)) break; /* rety with fixed request */ request = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; } while (request && (rc == STAT_SUCCESS)); /* * process results */ if ((rc == STAT_SUCCESS) && response) { if (response->errstat == SNMP_ERR_NOERROR) { /* * extract values from response */ for(var = response->variables; var; var = var->next_variable) { for (vp = values; vp->oid_len && vp->oid; vp++) { if (snmp_oid_compare(var->name, var->name_length, vp->oid, vp->oid_len) == 0) { if (mp_verbose > 1) print_variable(var->name, var->name_length, var); /* copy value, if not erroneous */ if ((var->type != SNMP_NOSUCHOBJECT) && (var->type != SNMP_NOSUCHINSTANCE) && (var->type != SNMP_ENDOFMIBVIEW)) copy_value(var, vp->type, vp->target_len, vp->target); else if (mp_verbose > 2) printf("OID not available: type=0x%X\n", var->type); /* short-circuit to next result variable */ break; } } } } else if ((ss->version == SNMP_VERSION_1) && (response->errstat == SNMP_ERR_NOSUCHNAME)) { if (mp_verbose > 3) printf("SNMP-V1: end of tree\n"); } else { /* * some other error occured */ if (mp_verbose > 0) printf("SNMP error: respose->errstat = %ld", response->errstat); rc = STAT_ERROR; } } else { /* * no response (i.e. all vars have been removed by * snmp_pid_fixup()) go ahead an assume an error */ rc = STAT_ERROR; } if (response) snmp_free_pdu(response); return rc; }
/* * Generic SNMP object fetcher * * st=1 snmpget() - query an agent and return a single value. * st=2 snmpwalk() - walk the mib and return a single dimensional array * containing the values. * st=3 snmprealwalk() and snmpwalkoid() - walk the mib and return an * array of oid,value pairs. * st=5-8 ** Reserved ** * st=11 snmpset() - query an agent and set a single value * */ void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st) { zval **a1, **a2, **a3, **a4, **a5, **a6, **a7; struct snmp_session session, *ss; struct snmp_pdu *pdu=NULL, *response; struct variable_list *vars; char *objid; oid name[MAX_NAME_LEN]; int name_length; int status, count,rootlen=0,gotroot=0; oid root[MAX_NAME_LEN]; char buf[2048]; char buf2[2048]; int keepwalking=1; long timeout=SNMP_DEFAULT_TIMEOUT; long retries=SNMP_DEFAULT_RETRIES; int myargc = ZEND_NUM_ARGS(); char type = (char) 0; char *value = (char *) 0; if (myargc < 3 || myargc > 7 || zend_get_parameters_ex(myargc, &a1, &a2, &a3, &a4, &a5, &a6, &a7) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(a1); convert_to_string_ex(a2); convert_to_string_ex(a3); if (st == 11) { if (myargc < 5) { WRONG_PARAM_COUNT; } convert_to_string_ex(a4); convert_to_string_ex(a5); if(myargc > 5) { convert_to_long_ex(a6); timeout = (*a6)->value.lval; } if(myargc > 6) { convert_to_long_ex(a7); retries = (*a7)->value.lval; } type = (*a4)->value.str.val[0]; value = (*a5)->value.str.val; } else { if(myargc > 3) { convert_to_long_ex(a4); timeout = (*a4)->value.lval; } if(myargc > 4) { convert_to_long_ex(a5); retries = (*a5)->value.lval; } } objid = (*a3)->value.str.val; if (st >= 2) { /* walk */ rootlen = MAX_NAME_LEN; if ( strlen(objid) ) { /* on a walk, an empty string means top of tree - no error */ if ( read_objid(objid, root, &rootlen) ) { gotroot = 1; } else { php_error(E_WARNING,"Invalid object identifier: %s\n", objid); } } if (gotroot == 0) { memmove((char *)root, (char *)objid_mib, sizeof(objid_mib)); rootlen = sizeof(objid_mib) / sizeof(oid); gotroot = 1; } } memset(&session, 0, sizeof(struct snmp_session)); session.peername = (*a1)->value.str.val; session.version = SNMP_VERSION_1; /* * FIXME: potential memory leak * This is a workaround for an "artifact" (Mike Slifcak) * in (at least) ucd-snmp 3.6.1 which frees * memory it did not allocate */ #ifdef UCD_SNMP_HACK session.community = (u_char *)strdup((*a2)->value.str.val); /* memory freed by SNMP library, strdup NOT estrdup */ #else session.community = (u_char *)(*a2)->value.str.val; #endif session.community_len = (*a2)->value.str.len; session.retries = retries; session.timeout = timeout; session.authenticator = NULL; snmp_synch_setup(&session); if ((ss = snmp_open(&session)) == NULL) { php_error(E_WARNING,"Could not open snmp\n"); RETURN_FALSE; } if (st >= 2) { memmove((char *)name, (char *)root, rootlen * sizeof(oid)); name_length = rootlen; if (array_init(return_value) == FAILURE) { php_error(E_WARNING, "Cannot prepare result array"); RETURN_FALSE; } } while(keepwalking) { keepwalking=0; if (st == 1) { pdu = snmp_pdu_create(SNMP_MSG_GET); name_length = MAX_NAME_LEN; if ( !read_objid(objid, name, &name_length) ) { php_error(E_WARNING,"Invalid object identifier: %s\n", objid); RETURN_FALSE; } snmp_add_null_var(pdu, name, name_length); } else if (st == 11) { pdu = snmp_pdu_create(SNMP_MSG_SET); if (snmp_add_var(pdu, name, name_length, type, value)) { php_error(E_WARNING,"Could not add variable: %s\n", name); RETURN_FALSE; } } else if (st >= 2) { pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); snmp_add_null_var(pdu, name, name_length); } retry: status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { for (vars = response->variables; vars; vars = vars->next_variable) { if (st >= 2 && st != 11 && (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) { continue; /* not part of this subtree */ } if (st != 11) { sprint_value(buf,vars->name, vars->name_length, vars); } #if 0 Debug("snmp response is: %s\n",buf); #endif if (st == 1) { RETVAL_STRING(buf,1); } else if (st == 2) { add_next_index_string(return_value,buf,1); /* Add to returned array */ } else if (st == 3) { sprint_objid(buf2, vars->name, vars->name_length); add_assoc_string(return_value,buf2,buf,1); } if (st >= 2 && st != 11) { if (vars->type != SNMP_ENDOFMIBVIEW && vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) { memmove((char *)name, (char *)vars->name,vars->name_length * sizeof(oid)); name_length = vars->name_length; keepwalking = 1; } } } } else { if (st != 2 || response->errstat != SNMP_ERR_NOSUCHNAME) { php_error(E_WARNING,"Error in packet.\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errstat == SNMP_ERR_NOSUCHNAME) { for (count=1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++); if (vars) { sprint_objid(buf,vars->name, vars->name_length); } php_error(E_WARNING,"This name does not exist: %s\n",buf); } if (st == 1) { if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GET)) != NULL) { goto retry; } } else if (st == 11) { if ((pdu = snmp_fix_pdu(response, SNMP_MSG_SET)) != NULL) { goto retry; } } else if (st >= 2) { if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) != NULL) { goto retry; } } RETURN_FALSE; } } } else if (status == STAT_TIMEOUT) { php_error(E_WARNING,"No Response from %s\n", (*a1)->value.str.val); RETURN_FALSE; } else { /* status == STAT_ERROR */ php_error(E_WARNING,"An error occurred, Quitting...\n"); RETURN_FALSE; } if (response) { snmp_free_pdu(response); } } /* keepwalking */ snmp_close(ss); }
int mp_snmp_query(netsnmp_session *ss, const mp_snmp_query_cmd *querycmd) { netsnmp_pdu *pdu; netsnmp_pdu *response; netsnmp_variable_list *vars; int status; const mp_snmp_query_cmd *p; pdu = snmp_pdu_create(SNMP_MSG_GET); for(p = querycmd; p->oid_len; p++) { snmp_add_null_var(pdu, p->oid, p->oid_len); } /* Send the SNMP Query */ do { status = snmp_synch_response(ss, pdu, &response); if (mp_verbose > 3) printf("snmp_synch_response() rc=%d\n", status); if (!response) return STAT_ERROR; if (status == STAT_SUCCESS && response->errindex == 0) break; if (mp_verbose > 3) printf(" errindex=%ld\n", response->errindex); pdu = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; } while (status == STAT_SUCCESS && pdu); if (!response) return status; /* Process the response. */ if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { for(vars = response->variables; vars; vars = vars->next_variable) { if (mp_verbose > 1) print_variable(vars->name, vars->name_length, vars); // Skip non existing vars if (vars->type == SNMP_NOSUCHOBJECT || vars->type == SNMP_NOSUCHINSTANCE || vars->type == SNMP_ENDOFMIBVIEW) continue; for(p = querycmd; p->oid_len; p++) { if (snmp_oid_compare(vars->name, vars->name_length, p->oid, p->oid_len) == 0) { copy_value(vars, p->type, p->target_len, p->target); break; } } } } else if (status != STAT_SUCCESS) { char *err; snmp_error(ss, NULL, NULL, &err); if (response) snmp_free_pdu(response); mp_snmp_deinit(); critical("SNMP Error: %s", err); } if (response) snmp_free_pdu(response); return status; }
int main(int argc, char *argv[]) { netsnmp_session session, *ss; netsnmp_pdu *pdu; netsnmp_pdu *response; netsnmp_variable_list *vars; int arg; int count; int current_name = 0; char *names[128]; oid name[MAX_OID_LEN]; size_t name_length; int status; int exitval = 0; /* * get the common command line arguments */ switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) { case -2: exit(0); case -1: usage(); exit(1); default: break; } if (arg >= argc) { fprintf(stderr, "Missing object name\n"); usage(); exit(1); } /* * get the object names */ for (; arg < argc; arg++) names[current_name++] = argv[arg]; SOCK_STARTUP; /* * Open an SNMP session. */ ss = snmp_open(&session); if (ss == NULL) { /* * diagnose snmp_open errors with the input netsnmp_session pointer */ snmp_sess_perror("snmpget", &session); SOCK_CLEANUP; exit(1); } /* * Create PDU for GET request and add object names to request. */ pdu = snmp_pdu_create(SNMP_MSG_GET); for (count = 0; count < current_name; count++) { name_length = MAX_OID_LEN; if (!snmp_parse_oid(names[count], name, &name_length)) { snmp_perror(names[count]); failures++; } else snmp_add_null_var(pdu, name, name_length); } if (failures) { SOCK_CLEANUP; exit(1); } /* * Perform the request. * * If the Get Request fails, note the OID that caused the error, * "fix" the PDU (removing the error-prone OID) and retry. */ retry: status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { for (vars = response->variables; vars; vars = vars->next_variable) print_variable(vars->name, vars->name_length, vars); } else { fprintf(stderr, "Error in packet\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errindex != 0) { fprintf(stderr, "Failed object: "); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) /*EMPTY*/; if (vars) { fprint_objid(stderr, vars->name, vars->name_length); } fprintf(stderr, "\n"); } exitval = 2; /* * retry if the errored variable was successfully removed */ if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_DONT_FIX_PDUS)) { pdu = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; if (pdu != NULL) { goto retry; } } } /* endif -- SNMP_ERR_NOERROR */ } else if (status == STAT_TIMEOUT) { fprintf(stderr, "Timeout: No Response from %s.\n", session.peername); exitval = 1; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmpget", ss); exitval = 1; } /* endif -- STAT_SUCCESS */ if (response) snmp_free_pdu(response); snmp_close(ss); SOCK_CLEANUP; return exitval; } /* end main() */
/* * Print a description of the network interfaces. */ void intpro(int interval) { oid varname[MAX_OID_LEN], *instance, *ifentry; size_t varname_len; int ifnum, cfg_nnets; oid curifip [4]; struct variable_list *var; struct snmp_pdu *request, *response; int status; int ifindex, oldindex = 0; struct _if_info { int ifindex; char name[128]; char ip[128], route[128]; char ioctets[20], ierrs[20], ooctets[20], oerrs[20], outqueue[20]; int operstatus; u_long netmask; struct in_addr ifip, ifroute; } *if_table, *cur_if; int max_name = 4, max_route = 7, max_ip = 7, max_ioctets = 7, max_ooctets = 7; int i; if (interval) { sidewaysintpr((unsigned)interval); return; } var = getvarbyname(Session, oid_cfg_nnets, sizeof(oid_cfg_nnets) / sizeof(oid)); if (var && var->val.integer) { cfg_nnets = *var->val.integer; snmp_free_var(var); } else { fprintf (stderr, "No response when requesting number of interfaces.\n"); return; } DEBUGMSGTL (("netstat:if", "cfg_nnets = %d\n", cfg_nnets)); memset (curifip, 0, sizeof (curifip)); if_table = (struct _if_info *) calloc (cfg_nnets, sizeof (*if_table)); cur_if = if_table; for (ifnum = 1; ifnum <= cfg_nnets; ifnum++) { register char *cp; request = snmp_pdu_create (SNMP_MSG_GETNEXT); memmove (varname, oid_ipadentaddr, sizeof (oid_ipadentaddr)); varname_len = sizeof (oid_ipadentaddr) / sizeof (oid); instance = varname + 9; memmove (varname + 10, curifip, sizeof (curifip)); *instance = IPIFINDEX; snmp_add_null_var (request, varname, varname_len); *instance = IPADDR; snmp_add_null_var (request, varname, varname_len); *instance = IPNETMASK; snmp_add_null_var (request, varname, varname_len); status = snmp_synch_response (Session, request, &response); if (status != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR) { fprintf (stderr, "SNMP request failed for interface %d, variable %ld out of %d interfaces (IP)\n", ifnum, response->errindex, cfg_nnets); cfg_nnets = ifnum; break; } for (var = response->variables; var; var = var->next_variable) { if (snmp_get_do_debugging()) { print_variable (var->name, var->name_length, var); } switch (var->name [9]) { case IPIFINDEX: ifindex = *var->val.integer; for (cur_if = if_table; cur_if->ifindex != ifindex && cur_if->ifindex != 0; cur_if++); cur_if->ifindex = ifindex; break; case IPADDR: memmove (curifip, var->name+10, sizeof (curifip)); memmove (&cur_if->ifip, var->val.string, sizeof (u_long)); break; case IPNETMASK: memmove (&cur_if->netmask, var->val.string, sizeof (u_long)); } } cur_if->ifroute.s_addr = cur_if->ifip.s_addr & cur_if->netmask; if (cur_if->ifroute.s_addr) strcpy(cur_if->route, netname (cur_if->ifroute, cur_if->netmask)); else strcpy(cur_if->route, "none"); if ((i = strlen(cur_if->route)) > max_route) max_route = i; if (cur_if->ifip.s_addr) strcpy(cur_if->ip, routename (cur_if->ifip)); else strcpy(cur_if->ip, "none"); if ((i = strlen(cur_if->ip)) > max_ip) max_ip = i; snmp_free_pdu (response); memmove (varname, oid_ifname, sizeof(oid_ifname)); varname_len = sizeof(oid_ifname) / sizeof(oid); ifentry = varname + 9; instance = varname + 10; request = snmp_pdu_create (SNMP_MSG_GETNEXT); *instance = oldindex; *ifentry = IFINDEX; snmp_add_null_var (request, varname, varname_len); *ifentry = IFNAME; snmp_add_null_var (request, varname, varname_len); *ifentry = IFOPERSTATUS; snmp_add_null_var (request, varname, varname_len); *ifentry = INOCTETS; snmp_add_null_var (request, varname, varname_len); *ifentry = OUTOCTETS; snmp_add_null_var (request, varname, varname_len); while ((status = snmp_synch_response (Session, request, &response)) == STAT_SUCCESS) { if (response->errstat != SNMP_ERR_NOSUCHNAME) break; if ((request = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) == NULL) break; snmp_free_pdu(response); } if (status != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR) { fprintf (stderr, "SNMP request failed for interface %d, variable %ld out of %d interfaces (IF)\n", ifnum, response->errindex, cfg_nnets); cfg_nnets = ifnum; break; } for (var = response->variables; var; var = var->next_variable) { if (snmp_get_do_debugging()) { print_variable (var->name, var->name_length, var); } if (!var->val.integer) continue; switch (var->name [9]) { case IFINDEX: ifindex = *var->val.integer; for (cur_if = if_table; cur_if->ifindex != ifindex && cur_if->ifindex != 0; cur_if++); cur_if->ifindex = ifindex; break; case INOCTETS: sprintf(cur_if->ioctets, "%lu", *var->val.integer); i = strlen(cur_if->ioctets); if (i > max_ioctets) max_ioctets = i; break; case OUTOCTETS: sprintf(cur_if->ooctets, "%lu", *var->val.integer); i = strlen(cur_if->ooctets); if (i > max_ooctets) max_ooctets = i; break; case IFNAME: oldindex = var->name[10]; if (var->val_len >= sizeof(cur_if->name)) var->val_len = sizeof(cur_if->name) - 1; memmove (cur_if->name, var->val.string, var->val_len); cur_if->name [var->val_len] = 0; if ((i = strlen(cur_if->name)+1) > max_name) max_name = i; break; case IFOPERSTATUS: cur_if->operstatus = *var->val.integer; break; } } snmp_free_pdu (response); if (intrface != NULL && strcmp(cur_if->name, intrface) != 0) { cur_if->name [0] = 0; continue; } if (cur_if->operstatus != MIB_IFSTATUS_UP) { cp = strchr(cur_if->name, '\0'); *cp++ = '*'; *cp = '\0'; } } printf("%*.*s %*.*s %*.*s %*.*s %*.*s ", -max_name, max_name, "Name", -max_route, max_route, "Network", -max_ip, max_ip, "Address", max_ioctets, max_ioctets, "Ioctets", max_ooctets, max_ooctets, "Ooctets"); putchar('\n'); for (ifnum = 0, cur_if = if_table; ifnum < cfg_nnets; ifnum++, cur_if++) { if (cur_if->name [0] == 0) continue; printf("%*.*s ", -max_name, max_name, cur_if->name); printf("%*.*s ", -max_route, max_route, cur_if->route); printf("%*.*s ", -max_ip, max_ip, cur_if->ip); printf("%*s %*s", max_ioctets, cur_if->ioctets, max_ioctets, cur_if->ooctets); putchar('\n'); } free(if_table); }
gchar * snmp_probe(gchar *peer, gint port, gchar *community) { oid sysDescr[MAX_OID_LEN]; size_t sysDescr_length; oid sysObjectID[MAX_OID_LEN]; size_t sysObjectID_length; oid sysUpTime[MAX_OID_LEN]; size_t sysUpTime_length; oid sysContact[MAX_OID_LEN]; size_t sysContact_length; oid sysName[MAX_OID_LEN]; size_t sysName_length; oid sysLocation[MAX_OID_LEN]; size_t sysLocation_length; struct snmp_session session, *ss; struct snmp_pdu *pdu, *response; struct variable_list *vars; int count; int status; char textbuf[1024]; char *result = NULL; char *tmp = NULL; /* transform interesting OIDs */ sysDescr_length = MAX_OID_LEN; if (!snmp_parse_oid("system.sysDescr.0", sysDescr, &sysDescr_length)) printf("error parsing oid: system.sysDescr.0\n"); sysObjectID_length = MAX_OID_LEN; if (!snmp_parse_oid("system.sysObjectID.0", sysObjectID, &sysObjectID_length)) printf("error parsing oid: system.sysObjectID.0\n"); sysUpTime_length = MAX_OID_LEN; if (!snmp_parse_oid("system.sysUpTime.0", sysUpTime, &sysUpTime_length)) printf("error parsing oid: system.sysUpTime.0\n"); sysContact_length = MAX_OID_LEN; if (!snmp_parse_oid("system.sysContact.0", sysContact, &sysContact_length)) printf("error parsing oid: system.sysContact.0\n"); sysName_length = MAX_OID_LEN; if (!snmp_parse_oid("system.sysName.0", sysName, &sysName_length)) printf("error parsing oid: system.sysName.0\n"); sysLocation_length = MAX_OID_LEN; if (!snmp_parse_oid("system.sysLocation.0", sysLocation, &sysLocation_length)) printf("error parsing oid: system.sysLocation.0\n"); /* initialize session to default values */ snmp_sess_init( &session ); session.version = SNMP_VERSION_1; session.community = community; session.community_len = strlen(community); session.peername = peer; #ifdef STREAM session.flags |= SNMP_FLAGS_STREAM_SOCKET; fprintf (stderr, "local port set to: %d\n", session.local_port); #endif /* * Open an SNMP session. */ ss = snmp_open(&session); if (ss == NULL){ fprintf (stderr, "local port set to: %d\n", session.local_port); snmp_sess_perror("snmp_open", &session); exit(1); } /* * Create PDU for GET request and add object names to request. */ pdu = snmp_pdu_create(SNMP_MSG_GET); snmp_add_null_var(pdu, sysDescr, sysDescr_length); snmp_add_null_var(pdu, sysObjectID, sysObjectID_length); snmp_add_null_var(pdu, sysUpTime, sysUpTime_length); snmp_add_null_var(pdu, sysContact, sysContact_length); snmp_add_null_var(pdu, sysName, sysName_length); snmp_add_null_var(pdu, sysLocation, sysLocation_length); /* * Perform the request. * * If the Get Request fails, note the OID that caused the error, * "fix" the PDU (removing the error-prone OID) and retry. */ retry: status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS){ if (response->errstat == SNMP_ERR_NOERROR){ /* just render all vars */ for(vars = response->variables; vars; vars = vars->next_variable) { snprint_variable(textbuf, 1023, vars->name, vars->name_length, vars); textbuf[1023] = '\0'; if (result) { tmp = result; result = g_strdup_printf("%s\n%s\n", tmp, textbuf); g_free(tmp); } else { result = g_strdup_printf("%s\n", textbuf); } } } else { fprintf(stderr, "Error in packet\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errstat == SNMP_ERR_NOSUCHNAME){ fprintf(stderr, "This name doesn't exist: "); for(count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) /*EMPTY*/ ; if (vars) fprint_objid(stderr, vars->name, vars->name_length); fprintf(stderr, "\n"); } /* retry if the errored variable was successfully removed */ pdu = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; if (pdu != NULL) goto retry; } /* endif -- SNMP_ERR_NOERROR */ } else if (status == STAT_TIMEOUT){ snmp_close(ss); return g_strdup_printf("Timeout: No Response from %s.\n", session.peername); } else { /* status == STAT_ERROR */ fprintf (stderr, "local port set to: %d\n", session.local_port); snmp_sess_perror("STAT_ERROR", ss); snmp_close(ss); return NULL; } /* endif -- STAT_SUCCESS */ if (response) snmp_free_pdu(response); snmp_close(ss); return result; }
/*! \fn char *snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) * \brief performs multiple OID snmp_get's in a single network call * * This function will a group of snmp OID's for a host. The host snmp * session must already be established. The function will modify elements of * the snmp_oids array with the results from the snmp api call. * */ void snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) { struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; struct variable_list *vars = NULL; int status; int i; int max_repetitions = 1; int non_repeaters = 0; int array_count; int index_count; /* get rid of some compiler warnings */ errstat = 0; errindex = 0; struct nameStruct { oid name[MAX_OID_LEN]; size_t name_len; } *name, *namep; /* load up oids */ namep = name = (struct nameStruct *) calloc(num_oids, sizeof(*name)); pdu = snmp_pdu_create(SNMP_MSG_GET); for (i = 0; i < num_oids; i++) { namep->name_len = MAX_OID_LEN; if (!snmp_parse_oid(snmp_oids[i].oid, namep->name, &namep->name_len)) { SPINE_LOG(("Host[%i] ERROR: Problems parsing Multi SNMP OID! (oid: %s)\n", current_host->id, snmp_oids[i].oid)); /* Mark this OID as "bad" */ SET_UNDEFINED(snmp_oids[i].result); }else{ snmp_add_null_var(pdu, namep->name, namep->name_len); } namep++; } status = STAT_DESCRIP_ERROR; /* execute the multi-get request */ retry: status = snmp_sess_synch_response(current_host->snmp_session, pdu, &response); /* liftoff, successful poll, process it!! */ if (status == STAT_SUCCESS) { if (response == NULL) { SPINE_LOG(("ERROR: An internal Net-Snmp error condition detected in Cacti snmp_get_multi\n")); status = STAT_ERROR; }else{ if (response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; for(i = 0; i < num_oids && vars; i++) { if (!IS_UNDEFINED(snmp_oids[i].result)) { #ifdef USE_NET_SNMP snmp_snprint_value(snmp_oids[i].result, RESULTS_BUFFER, vars->name, vars->name_length, vars); #else sprint_value(snmp_oids[i].result, vars->name, vars->name_length, vars); #endif vars = vars->next_variable; } } }else{ if (response->errindex != 0) { index_count = 1; array_count = 0; /* Find our index against errindex */ while (array_count < num_oids) { if (IS_UNDEFINED(snmp_oids[array_count].result) ) { array_count++; }else{ /* if we have found our error, exit */ if (index_count == response->errindex) { SET_UNDEFINED(snmp_oids[array_count].result); break; } array_count++; index_count++; } } /* remote the invalid OID from the PDU */ pdu = snmp_fix_pdu(response, SNMP_MSG_GET); /* free the previous response */ snmp_free_pdu(response); response = NULL; if (pdu != NULL) { /* retry the request */ goto retry; }else{ /* all OID's errored out so exit cleanly */ status = STAT_SUCCESS; } }else{ status = STAT_DESCRIP_ERROR; } } } } if (status != STAT_SUCCESS) { current_host->ignore_host = 1; for (i = 0; i < num_oids; i++) { SET_UNDEFINED(snmp_oids[i].result); } } if (response != NULL) { snmp_free_pdu(response); } }
int main(int argc, char *argv[]) { struct snmp_session session, *ss; struct snmp_pdu *pdu; struct snmp_pdu *response; struct variable_list *vars; int arg; int count; int current_name = 0; char *names[128]; oid name[MAX_OID_LEN]; int name_length; int status; /* get the common command line arguments */ arg = snmp_parse_args(argc, argv, &session); /* get the object names */ for(; arg < argc; arg++) names[current_name++] = argv[arg]; SOCK_STARTUP; /* open an SNMP session */ snmp_synch_setup(&session); ss = snmp_open(&session); if (ss == NULL){ snmp_perror("snmpget"); SOCK_CLEANUP; exit(1); } /* create PDU for GET request and add object names to request */ pdu = snmp_pdu_create(SNMP_MSG_GET); for(count = 0; count < current_name; count++){ name_length = MAX_OID_LEN; if (!snmp_parse_oid(names[count], name, &name_length)) { fprintf(stderr, "Invalid object identifier: %s\n", names[count]); failures++; } else snmp_add_null_var(pdu, name, name_length); } if (failures) { SOCK_CLEANUP; exit(1); } /* do the request */ retry: status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS){ if (response->errstat == SNMP_ERR_NOERROR){ for(vars = response->variables; vars; vars = vars->next_variable) print_variable(vars->name, vars->name_length, vars); } else { fprintf(stderr, "Error in packet\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errstat == SNMP_ERR_NOSUCHNAME){ fprintf(stderr, "This name doesn't exist: "); for(count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) ; if (vars) fprint_objid(stderr, vars->name, vars->name_length); fprintf(stderr, "\n"); } if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GET)) != NULL) goto retry; } } else if (status == STAT_TIMEOUT){ fprintf(stderr,"Timeout: No Response from %s.\n", session.peername); snmp_close(ss); SOCK_CLEANUP; exit(1); } else { /* status == STAT_ERROR */ snmp_perror("snmpget"); snmp_close(ss); SOCK_CLEANUP; exit(1); } if (response) snmp_free_pdu(response); snmp_close(ss); SOCK_CLEANUP; exit (0); }
int main(int argc, char *argv[]) { netsnmp_session session, *ss; netsnmp_pdu *pdu, *response; netsnmp_variable_list *vars; int arg; char *gateway; int count; struct varInfo *vip; u_int value = 0; struct counter64 c64value; float printvalue; time_t last_time = 0; time_t this_time; time_t delta_time; int sum; /* what the heck is this for, its never used? */ char filename[128] = { 0 }; struct timeval tv; struct tm tm; char timestring[64] = { 0 }, valueStr[64] = { 0}, maxStr[64] = { 0}; char outstr[256] = { 0 }, peakStr[64] = { 0}; int status; int begin, end, last_end; int print = 1; int exit_code = 1; SOCK_STARTUP; switch (arg = snmp_parse_args(argc, argv, &session, "C:", &optProc)) { case NETSNMP_PARSE_ARGS_ERROR: goto out; case NETSNMP_PARSE_ARGS_SUCCESS_EXIT: exit_code = 0; goto out; case NETSNMP_PARSE_ARGS_ERROR_USAGE: usage(); goto out; default: break; } gateway = session.peername; for (; optind < argc; optind++) { if (current_name >= MAX_ARGS) { fprintf(stderr, "%s: Too many variables specified (max %d)\n", argv[optind], MAX_ARGS); goto out; } varinfo[current_name++].name = argv[optind]; } if (current_name == 0) { usage(); goto out; } if (dosum) { if (current_name >= MAX_ARGS) { fprintf(stderr, "Too many variables specified (max %d)\n", MAX_ARGS); goto out; } varinfo[current_name++].name = NULL; } /* * open an SNMP session */ ss = snmp_open(&session); if (ss == NULL) { /* * diagnose snmp_open errors with the input netsnmp_session pointer */ snmp_sess_perror("snmpdelta", &session); goto out; } if (tableForm && timestamp) { printf("%s", gateway); } for (count = 0; count < current_name; count++) { vip = varinfo + count; if (vip->name) { vip->oidlen = MAX_OID_LEN; vip->info_oid = (oid *) malloc(sizeof(oid) * vip->oidlen); if (snmp_parse_oid(vip->name, vip->info_oid, &vip->oidlen) == NULL) { snmp_perror(vip->name); goto close_session; } sprint_descriptor(vip->descriptor, vip); if (tableForm) printf("\t%s", vip->descriptor); } else { vip->oidlen = 0; strlcpy(vip->descriptor, SumFile, sizeof(vip->descriptor)); } vip->value = 0; zeroU64(&vip->c64value); vip->time = 0; vip->max = 0; if (peaks) { vip->peak_count = -1; vip->peak = 0; vip->peak_average = 0; } } wait_for_period(period); end = current_name; sum = 0; while (1) { pdu = snmp_pdu_create(SNMP_MSG_GET); if (deltat) snmp_add_null_var(pdu, sysUpTimeOid, sysUpTimeLen); if (end == current_name) count = 0; else count = end; begin = count; for (; count < current_name && count < begin + varbindsPerPacket - deltat; count++) { if (varinfo[count].oidlen) snmp_add_null_var(pdu, varinfo[count].info_oid, varinfo[count].oidlen); } last_end = end; end = count; retry: status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { if (timestamp) { gettimeofday(&tv, (struct timezone *) 0); memcpy(&tm, localtime((time_t *) & tv.tv_sec), sizeof(tm)); if (((period % 60) && (!peaks || ((period * peaks) % 60))) || keepSeconds) sprintf(timestring, " [%02d:%02d:%02d %d/%d]", tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mon + 1, tm.tm_mday); else sprintf(timestring, " [%02d:%02d %d/%d]", tm.tm_hour, tm.tm_min, tm.tm_mon + 1, tm.tm_mday); } vars = response->variables; if (deltat) { if (!vars || !vars->val.integer) { fprintf(stderr, "Missing variable in reply\n"); continue; } else { this_time = *(vars->val.integer); } vars = vars->next_variable; } else { this_time = 1; } for (count = begin; count < end; count++) { vip = varinfo + count; if (vip->oidlen) { if (!vars || !vars->val.integer) { fprintf(stderr, "Missing variable in reply\n"); break; } vip->type = vars->type; if (vars->type == ASN_COUNTER64) { u64Subtract(vars->val.counter64, &vip->c64value, &c64value); memcpy(&vip->c64value, vars->val.counter64, sizeof(struct counter64)); } else { value = *(vars->val.integer) - vip->value; vip->value = *(vars->val.integer); } vars = vars->next_variable; } else { value = sum; sum = 0; } delta_time = this_time - vip->time; if (delta_time <= 0) delta_time = 100; last_time = vip->time; vip->time = this_time; if (last_time == 0) continue; if (vip->oidlen && vip->type != ASN_COUNTER64) { sum += value; } if (tableForm) { if (count == begin) { sprintf(outstr, "%s", timestring + 1); } else { outstr[0] = '\0'; } } else { sprintf(outstr, "%s %s", timestring, vip->descriptor); } if (deltat || tableForm) { if (vip->type == ASN_COUNTER64) { fprintf(stderr, "time delta and table form not supported for counter64s\n"); goto close_session; } else { printvalue = ((float) value * 100) / delta_time; if (tableForm) sprintf(valueStr, "\t%.2f", printvalue); else sprintf(valueStr, " /sec: %.2f", printvalue); } } else { printvalue = (float) value; sprintf(valueStr, " /%d sec: ", period); if (vip->type == ASN_COUNTER64) printU64(valueStr + strlen(valueStr), &c64value); else sprintf(valueStr + strlen(valueStr), "%u", value); } if (!peaks) { strcat(outstr, valueStr); } else { print = 0; if (vip->peak_count == -1) { if (wait_for_peak_start(period, peaks) == 0) vip->peak_count = 0; } else { vip->peak_average += printvalue; if (vip->peak < printvalue) vip->peak = printvalue; if (++vip->peak_count == peaks) { if (deltat) sprintf(peakStr, " /sec: %.2f (%d sec Peak: %.2f)", vip->peak_average / vip->peak_count, period, vip->peak); else sprintf(peakStr, " /%d sec: %.0f (%d sec Peak: %.0f)", period, vip->peak_average / vip->peak_count, period, vip->peak); vip->peak_average = 0; vip->peak = 0; vip->peak_count = 0; print = 1; strcat(outstr, peakStr); } } } if (printmax) { if (printvalue > vip->max) { vip->max = printvalue; } if (deltat) sprintf(maxStr, " (Max: %.2f)", vip->max); else sprintf(maxStr, " (Max: %.0f)", vip->max); strcat(outstr, maxStr); } if (print) { if (fileout) { sprintf(filename, "%s-%s", gateway, vip->descriptor); print_log(filename, outstr + 1); } else { if (tableForm) printf("%s", outstr); else printf("%s\n", outstr + 1); fflush(stdout); } } } if (end == last_end && tableForm) printf("\n"); } else { if (response->errstat == SNMP_ERR_TOOBIG) { if (response->errindex <= varbindsPerPacket && response->errindex > 0) { varbindsPerPacket = response->errindex - 1; } else { if (varbindsPerPacket > 30) varbindsPerPacket -= 5; else varbindsPerPacket--; } if (varbindsPerPacket <= 0) { exit_code = 5; break; } end = last_end; continue; } else if (response->errindex != 0) { fprintf(stderr, "Failed object: "); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++); if (vars) fprint_objid(stderr, vars->name, vars->name_length); fprintf(stderr, "\n"); /* * Don't exit when OIDs from file are not found on agent * exit_code = 1; * break; */ } else { fprintf(stderr, "Error in packet: %s\n", snmp_errstring(response->errstat)); exit_code = 1; break; } /* * retry if the errored variable was successfully removed */ if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_DONT_FIX_PDUS)) { pdu = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; if (pdu != NULL) goto retry; } } } else if (status == STAT_TIMEOUT) { fprintf(stderr, "Timeout: No Response from %s\n", gateway); response = NULL; exit_code = 1; break; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmpdelta", ss); response = NULL; exit_code = 1; break; } if (response) snmp_free_pdu(response); if (end == current_name) { wait_for_period(period); } } exit_code = 0; close_session: snmp_close(ss); out: SOCK_CLEANUP; return (exit_code); }
/* * Generic SNMP object fetcher * * st=1 GET * st=2 WALK */ void _php3_snmp(INTERNAL_FUNCTION_PARAMETERS, int st) { pval *a1, *a2, *a3; struct snmp_session session, *ss; struct snmp_pdu *pdu=NULL, *response; struct variable_list *vars; char *community, *hostname; char *objid; oid name[MAX_NAME_LEN]; int name_length; int status, count,rootlen=0,gotroot=0; oid root[MAX_NAME_LEN]; char buf[2048]; int keepwalking=1; static int mib_init=0; if (getParameters(ht, 3, &a1, &a2, &a3) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string(a1); convert_to_string(a2); convert_to_string(a3); hostname=a1->value.str.val; community=a2->value.str.val; objid=a3->value.str.val; if (!mib_init) { init_mib(); mib_init=1; } if (st==2) { /* walk */ rootlen = MAX_NAME_LEN; if (strlen(objid)) { /* on a walk, an empty string means top of tree - no error */ if (read_objid(objid, root, &rootlen)) { gotroot = 1; } else { php3_error(E_WARNING,"Invalid object identifier: %s\n", objid); } } if (gotroot == 0) { memmove((char *)root, (char *)objid_mib, sizeof(objid_mib)); rootlen = sizeof(objid_mib) / sizeof(oid); gotroot = 1; } } memset(&session, 0, sizeof(struct snmp_session)); session.peername = hostname; session.version = SNMP_VERSION_1; session.community = (u_char *)community; session.community_len = strlen((char *)community); session.retries = SNMP_DEFAULT_RETRIES; session.timeout = SNMP_DEFAULT_TIMEOUT; session.authenticator = NULL; snmp_synch_setup(&session); ss = snmp_open(&session); if (ss == NULL){ php3_error(E_WARNING,"Couldn't open snmp\n"); RETURN_FALSE; } if (st==2) { memmove((char *)name, (char *)root, rootlen * sizeof(oid)); name_length = rootlen; /* prepare result array */ array_init(return_value); } while(keepwalking) { keepwalking=0; if (st==1) pdu = snmp_pdu_create(GET_REQ_MSG); else if (st==2) pdu = snmp_pdu_create(GETNEXT_REQ_MSG); if (st==1) { name_length = MAX_NAME_LEN; if (!read_objid(objid, name, &name_length)) { php3_error(E_WARNING,"Invalid object identifier: %s\n", objid); RETURN_FALSE; } } snmp_add_null_var(pdu, name, name_length); retry: status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { for(vars = response->variables; vars; vars = vars->next_variable) { if (st==2 && (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) continue; /* not part of this subtree */ sprint_value(buf,vars->name, vars->name_length, vars); #if 0 Debug("snmp response is: %s\n",buf); #endif if (st==1) { RETVAL_STRING(buf,1); } else if (st==2) { /* Add to returned array */ add_next_index_string(return_value,buf,1); if (vars->type != SNMP_ENDOFMIBVIEW && vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) { memmove((char *)name, (char *)vars->name,vars->name_length * sizeof(oid)); name_length = vars->name_length; keepwalking = 1; } } } } else { if (st!=2 || response->errstat != SNMP_ERR_NOSUCHNAME) { php3_error(E_WARNING,"Error in packet.\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errstat == SNMP_ERR_NOSUCHNAME) { for(count=1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++); if (vars) sprint_objid(buf,vars->name, vars->name_length); php3_error(E_WARNING,"This name does not exist: %s\n",buf); } if (st==1) { if ((pdu = snmp_fix_pdu(response, GET_REQ_MSG)) != NULL) goto retry; } else if (st==2) { if ((pdu = snmp_fix_pdu(response, GETNEXT_REQ_MSG)) != NULL) goto retry; } RETURN_FALSE; } } } else if (status == STAT_TIMEOUT) { php3_error(E_WARNING,"No Response from %s\n", hostname); RETURN_FALSE; } else { /* status == STAT_ERROR */ php3_error(E_WARNING,"An error occurred, Quitting\n"); RETURN_FALSE; } if (response) snmp_free_pdu(response); } /* keepwalking */ snmp_close(ss); }
/*! \fn char *snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) * \brief performs multiple OID snmp_get's in a single network call * * This function will a group of snmp OID's for a host. The host snmp * session must already be established. The function will modify elements of * the snmp_oids array with the results from the snmp api call. * */ void snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) { struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; struct variable_list *vars = NULL; int status; int i; int max_repetitions = 1; int non_repeaters = 0; struct nameStruct { oid name[MAX_OID_LEN]; size_t name_len; } *name, *namep; /* load up oids */ namep = name = (struct nameStruct *) calloc(num_oids, sizeof(*name)); pdu = snmp_pdu_create(SNMP_MSG_GET); for (i = 0; i < num_oids; i++) { namep->name_len = MAX_OID_LEN; if (!snmp_parse_oid(snmp_oids[i].oid, namep->name, &namep->name_len)) { CACTID_LOG(("Host[%i] ERROR: Problems parsing Multi SNMP OID! (oid: %s)\n", current_host->id, snmp_oids[i].oid)); /* Mark this OID as "bad" */ SET_UNDEFINED(snmp_oids[i].result); }else{ snmp_add_null_var(pdu, namep->name, namep->name_len); } namep++; } status = STAT_DESCRIP_ERROR; /* execute the multi-get request */ retry: status = snmp_sess_synch_response(current_host->snmp_session, pdu, &response); /* liftoff, successful poll, process it!! */ if (status == STAT_SUCCESS) { if (response == NULL) { CACTID_LOG(("ERROR: An internal Net-Snmp error condition detected in Cacti snmp_get_multi\n")); status = STAT_ERROR; }else{ if (response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; for(i = 0; i < num_oids && vars; i++) { if (!IS_UNDEFINED(snmp_oids[i].result)) { #ifdef USE_NET_SNMP snmp_snprint_value(snmp_oids[i].result, sizeof(snmp_oids[i].result), vars->name, vars->name_length, vars); #else sprint_value(snmp_oids[i].result, vars->name, vars->name_length, vars); #endif vars = vars->next_variable; } } }else{ if (response->errindex != 0) { /* removed errored OID and then retry */ int count; /* Find our index against errindex */ count = 0; for(i = 0; i < num_oids && count < response->errindex; i++) { if ( ! IS_UNDEFINED(snmp_oids[i].result) ) { count++; } } i--; SET_UNDEFINED(snmp_oids[i].result); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) { } pdu = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; if (pdu != NULL) { goto retry; }else{ status = STAT_DESCRIP_ERROR; } }else{ status = STAT_DESCRIP_ERROR; } } } } if (status != STAT_SUCCESS) { current_host->ignore_host = 1; for (i = 0; i < num_oids; i++) { SET_UNDEFINED(snmp_oids[i].result); } } if (response != NULL) { snmp_free_pdu(response); } }
/* * If there was an error in the input pdu, creates a clone of the pdu * that includes all the variables except the one marked by the errindex. * The command is set to the input command and the reqid, errstat, and * errindex are set to default values. * If the error status didn't indicate an error, the error index didn't * indicate a variable, the pdu wasn't a get response message, or there * would be no remaining variables, this function will return NULL. * If everything was successful, a pointer to the fixed cloned pdu will * be returned. */ struct snmp_pdu *snmp_pdu_fix(struct snmp_pdu *pdu, int command) { return(snmp_fix_pdu(pdu, command)); }