File: structfill.C

package info (click to toggle)
npadmin 0.8-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 524 kB
  • ctags: 792
  • sloc: cpp: 3,514; ansic: 1,176; sh: 327; makefile: 52
file content (172 lines) | stat: -rw-r--r-- 4,618 bytes parent folder | download
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;
}