#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1