1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
#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;
}
}
//SNMP_structFiller::SNMP_structFiller(SNMP_session &sess,unsigned int num...):
// tabdef(NULL),oidseq(NULL),session(sess){
// va_list args;
// va_start(args,num);
// for(;num>0;num--)
// append(va_arg(args,char*),va_arg(args,Tags),va_arg(args,unsigned int));
// va_end(args);
// };
int SNMP_structFiller::fillStruct(OidSeq *data,unsigned char *curstruct){
for(TableEntry *cur=tabdef;cur!=NULL;cur=cur->next){
BerBase *curber;
if(!(curber=data->child(cur->oidstr)))
return 0;
if(curber->type()!=cur->type){
if(curber->type()==INT_TAG && cur->type==COUNTER_TAG)
fprintf(stderr,
"Warning: Counter returned when Integer expected for %s.\n",
cur->oidstr);
else if(curber->type()==COUNTER_TAG && cur->type==INT_TAG)
fprintf(stderr,
"Warning: Integer returned when Counter expected for %s.\n",
cur->oidstr);
else
assert(0); // wrong type returned
}
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 1;
}
void *SNMP_structFiller::get(void *tobefilled){
retseq=session.get(oidseq);
if(retseq==NULL)
throw SNMPERR_NoResponse;
if( !fillStruct(retseq,(unsigned char*)tobefilled))
return NULL;
return tobefilled;
}
void *SNMP_structFiller::get_next(void *tobefilled){
if(retseq){
delete oidseq;
oidseq=retseq;
retseq=NULL;
}
assert(retseq=session.get_next(oidseq));
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;
}
|