#include #include #include #include #include #include "structfill.h" TableEntry::TableEntry(const char *ostr,Tags thetype,unsigned int off, TableEntry *nxt):oidstr(ostr),type(thetype), offset(off),next(nxt){ assert(type==INT_TAG || type==TIME_TICK_TAG || type==OID_TAG || type==STRING_TAG || type==IPADDR_TAG || type==COUNTER_TAG); } void SNMP_structFiller::append(const char *oidstr,Tags tag, unsigned int offset){ assert(oidstr); assert(tabdef=new TableEntry(oidstr,tag,offset,tabdef)); if(oidseq) oidseq->append(oidstr); else oidseq=new OidSeq(1,oidstr); } void SNMP_structFiller::remove(const char *oidstr){ //delete the TableEntry assert(tabdef); /* if this fails you are trying to delete something from an empty structfiller. */ if(*tabdef==oidstr){ TableEntry *nextone=tabdef->next; delete tabdef; tabdef=nextone; } else { // search for it amongst the rest of the entries char test=0; for(TableEntry *cur=tabdef;cur!=NULL;cur=cur->next){ if(*cur->next==oidstr){ TableEntry *doomed=cur->next; cur->next=doomed->next; delete doomed; test=1; break; } } assert(test); /* if this fails you are trying to delete something from a structfiller that doesn't exist there. */ } //delete it off of the oidseq assert(oidseq); /* this should never fail. It means that there is something seriously wrong. the oidseq is out of sync with the table */ oidseq->remove(oidstr); } SNMP_structFiller::~SNMP_structFiller(){ if(oidseq) delete oidseq; if(retseq) delete retseq; while(tabdef){ TableEntry *tmp=tabdef->next; delete tabdef; tabdef=tmp; } } int SNMP_structFiller::fillStruct(OidSeq *data, unsigned char *curstruct){ int retval=1; for(TableEntry *cur=tabdef;cur!=NULL;cur=cur->next){ BerBase *curber; if(!(curber=data->child(cur->oidstr))){ retval=0; continue; } if(curber->type()!=cur->type){ if(curber->type()==INT_TAG && cur->type==COUNTER_TAG) fprintf(stderr,"Warning: Counter returned when Integer expected for " "%s.Buggy firmware?\n",cur->oidstr); else if(curber->type()==COUNTER_TAG && cur->type==INT_TAG) fprintf(stderr,"Warning: Integer returned when Counter expected for " "%s. Buggy firmware?\n",cur->oidstr); else{ fprintf(stderr,"Warning: Printer returned a value of type 0x%x when a " "value of 0x%x was expected for %s. Buggy firmware?" "\n",curber->type(),cur->type,cur->oidstr); throw SNMP_error_oid(cur->oidstr); } } unsigned char *inside=curstruct+cur->offset; switch(cur->type){ case INT_TAG: case COUNTER_TAG: *((long*)inside)=((BerInt*)curber)->value(); break; case TIME_TICK_TAG: *((unsigned long*)inside)=((BerTimeTick*)curber)->value(); break; case IPADDR_TAG: assert(((BerIPAddr*)curber)->Len()==4); assert(*((unsigned char**)inside)=new unsigned char[4]); memcpy(*((unsigned char**)inside),((BerIPAddr*)curber)->IPaddr(),4); break; case OID_TAG: case STRING_TAG: assert(*((char**)inside)=new char[256]); int len=((BerString*)curber)->copy(*((char**)inside),256); (*(char**)inside)[len]=0; *(char**)inside=(char*)realloc(*(char**)inside,len+1); break; } } return retval; } void *SNMP_structFiller::get(void *tobefilled){ retseq=session.get(oidseq); if(retseq==NULL) throw SNMPERR_NoResponse; if( !fillStruct(retseq,(unsigned char*)tobefilled)){ fprintf(stderr,"Warning: printer did not respond with a value for one of the OIDs. Buggy firmware?\n"); return NULL; } return tobefilled; } void *SNMP_structFiller::get_next(void *tobefilled){ if(retseq){ delete oidseq; oidseq=retseq; retseq=NULL; } retseq=session.get_next(oidseq); if(retseq==NULL) throw SNMPERR_NoResponse; if(!fillStruct(retseq,(unsigned char*)tobefilled)) return NULL; return tobefilled; } void *SNMP_table::get(unsigned int &idx){ idx=0; // sort of a second return value unsigned int maxlen=10; void *retval; assert(retval=malloc(structlen*maxlen)); /* this isn't strictly necessary but it does make debugging easier notice I don't do it below when the array is resized. */ memset(retval,0,structlen*maxlen); // while we are still in the table while(get_next(((unsigned char*)retval)+idx*structlen)){ idx++; if(idx==maxlen){ //this could be really slow with big structures. maxlen+=10; assert(retval=realloc(retval,structlen*maxlen)); } } assert(retval=realloc(retval,structlen*(idx+1))); return retval; }