/* * snmpstuff.c * * $Revision: 1.13 $ * * These functions deal with processing mib/snmp data. * A bunch of this is ucd-snmp code hacked to deal with * a GUI interface. * * Last Modified: * $Author: ahodgen $ * $Date: 2002/06/21 11:45:18 $ * */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include "callbacks.h" #include "interface.h" #include "details.h" #include "configuration.h" #include "snmpstuff.h" #define GTK_SNMP_PERROR disperror(snmp_api_errstring(snmp_errno)); #ifdef HAVE_BROKEN_API # define snprint_variable(a,b,c,d,e) \ sprint_variable(binit(NULL, a, b),c,d,e); # define snprint_objid(a,b,c,d) \ sprint_variable(binit(NULL,a,b),c,d); #else # ifndef HAVE_NETSNMP # define snprint_variable(a,b,c,d,e) \ sprint_variable(a,c,d,e); # define snprint_objid(a,b,c,d) \ sprint_objid(a,c,d) # endif #endif oid objid_mib[] = {1, 3, 6, 1}; int numprinted; struct tree *mibtree; #define READ_ONLY 0 #define READ_WRITE 1 struct snmp_session *mbrowse_create_snmp_session(struct snmp_session *session,int comm_type) { config_t *config; config = get_config(); snmp_sess_init(session); session->version = config->snmp_ver; session->peername = get_hostname(); session->retries = config->snmp_retries; session->timeout = config->snmp_timeout * 1000000L; session->remote_port = config->snmp_port; switch(comm_type) { case READ_WRITE: session->community = get_writecomm(); break; case READ_ONLY: default: session->community = get_readcomm(); break; } session->community_len = strlen(session->community); return(snmp_open(session)); } struct tree *init_mbrowse_snmp(void) { snmp_set_save_descriptions(1); init_snmp("browser"); /* init_mib_internals(); adopt_orphans();*/ mibtree = read_all_mibs(); snmp_set_suffix_only(1); return(mibtree); } static void _snmpget(struct snmp_session *ss, oid *theoid, size_t theoid_len, gpointer window) { struct snmp_pdu *pdu, *response; struct variable_list *vars; int status; char buf[SPRINT_MAX_LEN]; pdu = snmp_pdu_create(SNMP_MSG_GET); snmp_add_null_var(pdu, theoid, theoid_len); status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { for(vars = response->variables; vars; vars = vars->next_variable) { numprinted++; snprint_variable(buf, sizeof(buf),vars->name,vars->name_length,vars); strcat(buf,"\n"); gtk_text_insert(window,NULL,NULL,NULL,buf,-1); } } if (response) snmp_free_pdu(response); } void snmpget(char *host,char *object,char *community,gpointer user_data) { char buf[SPRINT_MAX_LEN],temp[SPRINT_MAX_LEN]; char *error; struct snmp_session session, *ss; struct snmp_pdu *pdu; struct snmp_pdu *response = NULL; struct variable_list *vars; int count; oid name[MAX_OID_LEN]; size_t name_length = MAX_OID_LEN; int status; ss = mbrowse_create_snmp_session(&session,READ_ONLY); if (ss == NULL){ /* diagnose snmp_open errors with the input struct snmp_session pointer */ snmp_error(&session,NULL,NULL,&error); disperror(error); return; } pdu = snmp_pdu_create(SNMP_MSG_GET); if (!snmp_parse_oid(object, name, &name_length)) { GTK_SNMP_PERROR; return; } else snmp_add_null_var(pdu, name, name_length); 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) { snprint_variable(buf,sizeof(buf),vars->name,vars->name_length,vars); gtk_text_insert(user_data,NULL,NULL,NULL,buf,-1); } } else { sprintf(buf,"Error in Packet: %s",snmp_errstring(response->errstat)); disperror(buf); if (response->errstat == SNMP_ERR_NOSUCHNAME){ sprintf(temp,"This name doesn't exist: "); for(count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) if (vars) { snprint_objid(buf,sizeof(buf),vars->name,vars->name_length); strcat(temp,buf); } disperror(temp); } } /* endif -- SNMP_ERR_NOERROR */ } else if (status == STAT_TIMEOUT){ disperror("Timed out. (Check community string)"); snmp_close(ss); return; } else { /* status == STAT_ERROR */ snmp_error(&session,NULL,NULL,&error); disperror(error); snmp_close(ss); return; } /* endif -- STAT_SUCCESS */ if (response) snmp_free_pdu(response); snmp_close(ss); } void snmpwalk(char *host,char *object,char *community,gpointer user_data) { char buf[SPRINT_MAX_LEN],temp[SPRINT_MAX_LEN]; char *error; struct snmp_session session, *ss; struct snmp_pdu *pdu; struct snmp_pdu *response = NULL; struct variable_list *vars; int count; oid root[MAX_OID_LEN]; size_t rootlen = MAX_OID_LEN; oid name[MAX_OID_LEN]; size_t name_length = MAX_OID_LEN; int status = 0; int notdone = 1; numprinted=0; ss = mbrowse_create_snmp_session(&session,READ_ONLY); if (ss == NULL){ /* diagnose snmp_open errors with the input struct snmp_session pointer */ snmp_error(&session,NULL,NULL,&error); disperror(error); return; } if (object && strlen(object)) { if (!snmp_parse_oid(object, root, &rootlen)) { GTK_SNMP_PERROR; return; } } else { memmove(root, objid_mib, sizeof(objid_mib)); rootlen = sizeof(objid_mib) / sizeof(oid); } memmove(name, root, rootlen * sizeof(oid)); name_length = rootlen; _snmpget(ss, root, rootlen, user_data); while(notdone) { pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); snmp_add_null_var(pdu, name, name_length); /* do the request */ status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS){ if (response->errstat == SNMP_ERR_NOERROR){ /* check resulting variables */ for(vars = response->variables; vars; vars = vars->next_variable){ if ((vars->name_length < rootlen) || (memcmp(root, vars->name, rootlen * sizeof(oid))!=0)) { /* not part of this subtree */ notdone = 0; continue; } numprinted++; snprint_variable(buf,sizeof(buf),vars->name,vars->name_length,vars); strcat(buf,"\n"); gtk_text_insert(user_data,NULL,NULL,NULL,buf,-1); if ((vars->type != SNMP_ENDOFMIBVIEW) && (vars->type != SNMP_NOSUCHOBJECT) && (vars->type != SNMP_NOSUCHINSTANCE)){ /* not an exception value */ memmove((char *)name, (char *)vars->name, vars->name_length * sizeof(oid)); name_length = vars->name_length; } else /* an exception value, so stop */ notdone = 0; } } else { /* error in response, print it */ notdone = 0; if (response->errstat == SNMP_ERR_NOSUCHNAME){ gtk_text_insert(user_data,NULL,NULL,NULL,"End of MIB\n",-1); } else { sprintf(buf,"Error in Packet: %s", snmp_errstring(response->errstat)); disperror(buf); if (response->errstat == SNMP_ERR_NOSUCHNAME) { sprintf(temp,"The request for this object identifier failed: "); for(count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) if (vars) { snprint_objid(buf,sizeof(buf),vars->name,vars->name_length); strcat(temp,buf); } disperror(temp); } } } } else if (status == STAT_TIMEOUT){ disperror("Timed out. (Check community string)"); notdone = 0; snmp_close(ss); return; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmpwalk", ss); notdone = 0; } if (response) snmp_free_pdu(response); } if (numprinted == 0 && status == STAT_SUCCESS) { /* no printed successful results, which may mean we were pointed at an only existing instance. Attempt a GET, just for get measure. */ _snmpget(ss, root, rootlen, user_data); } snmp_close(ss); sprintf(buf,"Variables found: %d", numprinted); disperror(buf); } void snmpset(char *host,char *object,char *community,char *value, gpointer window) { char buf[SPRINT_MAX_LEN]; char *error; struct snmp_session session,*ss; struct snmp_pdu *pdu; struct snmp_pdu *response; struct variable_list *vars; struct tree *subtree; oid name[MAX_OID_LEN]; size_t name_length = MAX_OID_LEN; int status; char type = 0; char *as; if (!value || (*value == 0)) { disperror("Value is required for a set."); return; } if (!read_objid(object,name,&name_length)) { disperror("Invalid Object ID"); return; } subtree = get_tree(name,name_length,get_tree_head()); as = get_as(); if (as && *as) { switch(*as) { case 'S': type = 's'; break; case 'I': type = 'd'; break; case 'H': type = 'x'; break; default: type = '='; break; } } else { switch(subtree->type) { case TYPE_OBJID: type = 'o'; break; case TYPE_OCTETSTR: type = 's'; break; case TYPE_IPADDR: type = 'a'; break; case TYPE_TIMETICKS: type = 't'; break; case TYPE_COUNTER: case TYPE_COUNTER64: case TYPE_GAUGE: case TYPE_INTEGER: case TYPE_UINTEGER: case TYPE_INTEGER32: case TYPE_UNSIGNED32: type='i'; break; case TYPE_OPAQUE: case TYPE_NULL: case TYPE_BITSTRING: case TYPE_NSAPADDRESS: case TYPE_NETADDR: case TYPE_OTHER: default: ; } } if (type == 0) { disperror("Cannot handle object type at this time."); return; } ss = mbrowse_create_snmp_session(&session,READ_WRITE); if (ss == NULL) { snmp_error(&session,NULL,NULL,&error); disperror(error); return; } pdu = snmp_pdu_create(SNMP_MSG_SET); if (!snmp_parse_oid(object,name,&name_length)) { GTK_SNMP_PERROR; return; } else { if (snmp_add_var(pdu,name,name_length,type,value)) { GTK_SNMP_PERROR; return; } } 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) { snprint_variable(buf,sizeof(buf),vars->name,vars->name_length,vars); strcat(buf,"\n"); gtk_text_insert(window,NULL,NULL,NULL,buf,-1); } } else { sprintf(buf,"Error in Packet: %s",snmp_errstring(response->errstat)); disperror(buf); } } else if (status == STAT_TIMEOUT) { disperror("Timed out. (Check community string)"); snmp_close(ss); return; } else { snmp_error(&session,NULL,NULL,&error); disperror(error); snmp_close(ss); } if (response) snmp_free_pdu(response); snmp_close(ss); }