1 #include <string.h>
2 #include <assert.h>
3 #include <stdarg.h>
4 #include <stdio.h>
5 
6 #include "ber.h"
7 
8 /* berSequence - sequences are wrappers for other encoded pieces of data.
9  * basically all that they do is give mark their beginning and have a length.
10  * the tricky bit is that they can be recursive. This is the real reason for
11  * mbufs.
12  * You sort of insert the other information into the sequence. The ber encoded
13  * information that you insert into a sequence is assumed to be owned by the
14  * sequence. It actually throws it away very shortly and just keeps the mbufs.
15  */
16 
~BerSequence()17 BerSequence::~BerSequence(){
18   for(BerBase *cur=head; cur!=NULL; ){
19     BerBase *tmp=cur;
20     cur=cur->next;
21     delete tmp;
22   }
23 }
24 
BerSequence(unsigned char * str)25 BerSequence::BerSequence(unsigned char *str){
26   head=NULL;
27   tail=NULL;
28   assert(str[0]&CONSTRUCTOR_TAG);
29   unsigned char headlen;
30   tag=(Tags)str[0];
31   seqlen=unpack_len(str,headlen);
32 
33   unsigned long myseqlen=0;
34   unsigned char junk; // used to store the headerlen and then dispose of it
35   for(unsigned char *curpos=str+headlen;curpos<str+headlen+seqlen;
36       curpos+=unpack_len(curpos,junk)+junk){
37     BerBase *newone;
38 //     char tmpbuf[10240];
39 //     int tmplen;
40     switch(*curpos){
41     case INT_TAG:
42     case COUNTER_TAG:
43       newone=new BerInt(curpos);
44 //       tmplen=newone->print(tmpbuf,10239);
45 //       tmpbuf[tmplen]=0;
46 //       printf("%s\n\n",tmpbuf);
47       break;
48     case STRING_TAG:
49       newone=new BerString(curpos);
50       break;
51     case NULL_TAG:
52       newone=new BerNull(curpos);
53       break;
54     case OID_TAG:
55       newone=new BerOid(curpos);
56       break;
57     case TIME_TICK_TAG:
58       newone=new BerTimeTick(curpos);
59       break;
60     case IPADDR_TAG:
61       newone=new BerIPAddr(curpos);
62       break;
63     default:
64       newone=new BerSequence(curpos);
65     }
66     assert(newone);
67     if(head==NULL)
68       tail=head=newone;
69     else {
70       tail->next=newone;
71       tail=tail->next;
72     }
73     myseqlen+=newone->fulllen();
74   }
75   unsigned char *tempstr=start_data((Tags)str[0],myseqlen,headlen);
76   assert(edatacache=new BerEncodedData(tempstr,headlen));
77   // shorten the string because start_data creates a space big enough for the
78   // data as well.
79   edatacache->Data((unsigned char*)realloc(edatacache->Data(),headlen));
80 }
81 
getdata()82 BerEncodedData *BerSequence::getdata(){
83   if(edatacache==NULL){
84     unsigned char headlen;
85     unsigned char *tmp=start_data(tag,seqlen,headlen);
86     tmp=(unsigned char*)realloc(tmp,headlen);
87     assert(edatacache=new BerEncodedData(tmp,headlen));
88   }
89   if(edatacache->next==NULL){
90     BerEncodedData *tail=edatacache;
91     for(BerBase *cur=head;cur!=NULL; cur=cur->next){
92       tail->next=cur->getdata();
93       while(tail->next)
94 	tail=tail->next; // walk to the end of the list.
95     }
96   }
97   return edatacache;
98 }
99 
encode()100 BerEncodedData *BerSequence::encode(){
101   BerEncodedData *datlisthead=NULL,*curdat=NULL,*bedtail=NULL;
102 
103   // string up the data
104   for(BerBase *cur=head; cur!=NULL; cur=cur->next){
105     // go to the end of the list.
106     curdat=cur->getdata();
107     if(datlisthead==NULL){
108       datlisthead=bedtail=curdat;
109     }else{
110       bedtail->next=curdat;
111       bedtail=bedtail->next;
112     }
113     while(bedtail->next)
114       bedtail=bedtail->next;
115   }
116 
117   // encode the data
118   unsigned char headerlen;
119   unsigned char *retval=start_data(tag,seqlen,headerlen);
120   unsigned char *curpos=retval+headerlen;
121   for(curdat=datlisthead; curdat!=NULL;
122       curpos+=curdat->Length(), curdat=curdat->next){
123     memcpy(curpos, curdat->Data(), curdat->Length());
124   }
125   return new BerEncodedData(retval,seqlen+headerlen);
126 }
127 
BerSequence(Tags newtag,unsigned int entries...)128 BerSequence::BerSequence(Tags newtag, unsigned int entries ...){
129   va_list berObs;
130   va_start(berObs,entries);
131   tag=newtag;
132 
133   if(entries==0){
134     head=tail=NULL;
135     return;
136   }
137   BerBase *curBer=va_arg(berObs,BerBase*);
138   assert(curBer);
139   head=tail=curBer;
140   seqlen=curBer->fulllen();
141 
142   //only count down to one because we have already taken one.
143   for(;entries>1;entries--){
144     curBer=va_arg(berObs,BerBase*);
145     assert(curBer);
146     seqlen+=curBer->fulllen();
147     tail->next=curBer;
148     tail=tail->next;
149   }
150 
151   va_end(berObs);
152 }
153 
154 // /* never tested */
155 // BerSequence::prepend(unsigned int num ...){
156 //   va_list newones;
157 //   va_start(newones,num);
158 
159 //   BerBase *newlist,*newtail;
160 //   newtail=newlist=va_arg(newones,BerBase*);
161 //   assert(newlist);
162 //   seqlen+=newlist->fulllen();
163 //   for(;num>1;num--){
164 //     BerBase *curber=va_arg(newones,BerBase*);
165 //     assert(curber);x
166 //     seqlen+=curber->fulllen();
167 //     newtail->next=curber;
168 //     newtail=newtail->next;
169 //   }
170 //   newtail->next=head;
171 //   head=newlist;
172 
173 //   va_end(newones);
174 // }
175 
176 
append(unsigned int num...)177 void BerSequence::append(unsigned int num ...){
178   va_list newones;
179   va_start(newones,num);
180 
181   if(head==NULL){
182       head=tail=va_arg(newones,BerBase*);
183       seqlen=tail->fulllen();
184       num--;
185   }
186 
187   while(num--){
188     tail->next=va_arg(newones,BerBase*);
189     assert(tail->next);
190     tail=tail->next;
191     seqlen+=tail->fulllen();
192   }
193 
194   if(edatacache){
195     delete edatacache;
196     edatacache=NULL;
197   }
198   va_end(newones);
199 }
200 
peek(unsigned int num)201 BerBase *BerSequence::peek(unsigned int num){
202   BerBase *cur;
203   for(cur=head;num && cur!=NULL;num--,cur=cur->next);
204   return cur;
205 }
206 
extract(unsigned int num)207 BerBase *BerSequence::extract(unsigned int num){
208   BerBase *cur,*prev=NULL;
209   for(cur=head;num && cur!=NULL;num--,cur=cur->next)
210     prev=cur;
211   if(cur==NULL) return NULL;
212 
213   // remove its length
214   /* The inital approach was to just subtract the fulllen but fullen walks
215      the list of the encoded data and so in effect it returns the remainder
216      of the sequence. Thus the sequence is too short. This subtracts the
217      correct amount and leaves the semantics of fulllen the same. However, I
218      am not sure that is the right thing to do. It might be worth it to change
219      the functioning of fulllen but I didn't want to take the time to figure
220      out all the other ways that might affect the code. */
221   unsigned char headlen;
222   seqlen-=unpack_len(cur->edatacache->Data(),headlen);
223   seqlen-=headlen;
224 
225   /* got to fix up edatacache so that it matches current data */
226   unsigned char *newdat=start_data((Tags)(edatacache->Data())[0],seqlen,
227 				   headlen);
228   assert(newdat=(unsigned char*)realloc(newdat,headlen));
229   BerEncodedData *oldedc=edatacache;
230   assert(edatacache=new BerEncodedData(newdat,headlen));
231   edatacache->next=oldedc->next;
232   delete oldedc;
233 
234   BerEncodedData *oldend;
235   if(cur==head){
236     head=head->next;
237   } else {
238     prev->next=cur->next;
239     /* find the entry that is cur's edatacache
240        and set it to the value of cur->next->edatacache
241        kind of sew the lists together */
242     if(cur->next!=NULL){
243       for(oldend=prev->edatacache;oldend->next!=cur->edatacache;
244 	  oldend=oldend->next){
245 	assert(oldend->next!=NULL); /* I don't know what this would mean. If
246 				       it ever comes up. I guess I will have
247 				       to deal with it. */
248       }
249       oldend->next=cur->next->edatacache;
250     }
251   }
252   // make is so that cur->edatacache list doesn't merge into this list
253   if(cur->next){
254     for(oldend=cur->edatacache; oldend->next!=cur->next->edatacache;
255 	oldend=oldend->next);
256     oldend->next=NULL;
257   }
258 
259   if(cur==tail){
260     tail=prev;
261   }
262   cur->next=NULL;
263 
264   return cur;
265 }
266 
print(char * buf,unsigned int len)267 int BerSequence::print(char *buf, unsigned int len){
268   len-=2;
269   if(!len) return -1;
270   buf[0]='(';
271   buf[1]=' ';
272   buf+=2;
273   int totlen=1;
274   for( BerBase *cur=head; cur!=NULL; cur=cur->next){
275     int i=cur->print(buf,len);
276     if(i==-1) return -1;
277     len-=i+1;
278     buf+=i;
279     buf[0]=' ';
280     buf++;
281     totlen+=i+1;
282   }
283   if(!--len) return -1;
284   buf[0]=')';
285   buf[1]=' ';
286   return totlen+2;
287 }
288 
289 
290 
291