]> git.stg.codes - ssmd.git/blob - 3rdparty/snmp++/src/oid.cpp
Initial adding
[ssmd.git] / 3rdparty / snmp++ / src / oid.cpp
1 /*_############################################################################
2   _## 
3   _##  oid.cpp  
4   _##
5   _##  SNMP++v3.2.25
6   _##  -----------------------------------------------
7   _##  Copyright (c) 2001-2010 Jochen Katz, Frank Fock
8   _##
9   _##  This software is based on SNMP++2.6 from Hewlett Packard:
10   _##  
11   _##    Copyright (c) 1996
12   _##    Hewlett-Packard Company
13   _##  
14   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15   _##  Permission to use, copy, modify, distribute and/or sell this software 
16   _##  and/or its documentation is hereby granted without fee. User agrees 
17   _##  to display the above copyright notice and this license notice in all 
18   _##  copies of the software and any documentation of the software. User 
19   _##  agrees to assume all liability for the use of the software; 
20   _##  Hewlett-Packard and Jochen Katz make no representations about the 
21   _##  suitability of this software for any purpose. It is provided 
22   _##  "AS-IS" without warranty of any kind, either express or implied. User 
23   _##  hereby grants a royalty-free license to any and all derivatives based
24   _##  upon this software code base. 
25   _##  
26   _##  Stuttgart, Germany, Thu Sep  2 00:07:47 CEST 2010 
27   _##  
28   _##########################################################################*/
29 /*===================================================================
30
31   Copyright (c) 1999
32   Hewlett-Packard Company
33
34   ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
35   Permission to use, copy, modify, distribute and/or sell this software
36   and/or its documentation is hereby granted without fee. User agrees
37   to display the above copyright notice and this license notice in all
38   copies of the software and any documentation of the software. User
39   agrees to assume all liability for the use of the software; Hewlett-Packard
40   makes no representations about the suitability of this software for any
41   purpose. It is provided "AS-IS" without warranty of any kind,either express
42   or implied. User hereby grants a royalty-free license to any and all
43   derivatives based upon this software code base.
44
45   O I D. C P P
46
47   OID CLASS IMPLEMENTATION
48
49   DESIGN + AUTHOR:         Peter E. Mellquist
50
51   DESCRIPTION:
52   This module contains the implementation of the oid class. This
53   includes all protected and public member functions. The oid class
54   may be compiled stand alone without the use of any other library.
55 =====================================================================*/
56 char oid_cpp_version[]="#(@) SNMP++ $Id: oid.cpp 1742 2010-04-29 19:08:54Z katz $";
57
58 //---------[ external C libaries used ]--------------------------------
59 #include <stdio.h>                // standard io
60 #if !(defined (CPU) && CPU == PPC603)
61 #include <memory.h>               // memcpy's
62 #endif
63 #include <string.h>               // strlen, etc..
64 #include <stdlib.h>               // standard library
65 #include <ctype.h>                // isdigit
66 #include <stdlib.h>               // malloc, free
67
68 #include "snmp_pp/oid.h"                  // include def for oid class
69
70 #ifdef SNMP_PP_NAMESPACE
71 namespace Snmp_pp {
72 #endif
73
74 #define  SNMPBUFFSIZE 11          // size of scratch buffer
75 #define  SNMPCHARSIZE 11          // an individual oid instance as a string
76
77 /* Borlands isdigit has a bug */
78 #ifdef __BCPLUSPLUS__
79 #define my_isdigit(c) ((c) >= '0' && (c) <= '9')
80 #else
81 #define my_isdigit isdigit
82 #endif
83
84 //=============[Oid::Oid(void)]============================================
85 // constructor using no arguments
86 // initialize octet ptr and string
87 // ptr to null
88 Oid::Oid() : iv_str(0), iv_part_str(0), m_changed(true)
89 {
90   smival.syntax = sNMP_SYNTAX_OID;
91   smival.value.oid.len = 0;
92   smival.value.oid.ptr = 0;
93 }
94
95
96 //=============[Oid::Oid(const char *dotted_string ]=====================
97 // constructor using a dotted string
98 //
99 // do a string to oid using the string passed in
100 Oid::Oid(const char *oid_string, const bool is_dotted_oid_string)
101   : iv_str(0), iv_part_str(0), m_changed(true)
102 {
103   smival.syntax = sNMP_SYNTAX_OID;
104   smival.value.oid.len = 0;
105   smival.value.oid.ptr = 0;
106
107   if (is_dotted_oid_string)
108     StrToOid(oid_string, &smival.value.oid);
109   else
110     set_data(oid_string, oid_string ? strlen(oid_string) : 0);
111 }
112
113
114 //=============[Oid::Oid(const Oid &oid) ]================================
115 // constructor using another oid object
116 //
117 // do an oid copy using the oid object passed in
118 Oid::Oid(const Oid &oid)
119   : iv_str(0), iv_part_str(0), m_changed(true)
120 {
121   smival.syntax = sNMP_SYNTAX_OID;
122   smival.value.oid.len = 0;
123   smival.value.oid.ptr = 0;
124
125   // allocate some memory for the oid
126   // in this case the size to allocate is the same size as the source oid
127   if (oid.smival.value.oid.len)
128   {
129     smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid.smival.value.oid.len];
130     if (smival.value.oid.ptr)
131       OidCopy((SmiLPOID)&(oid.smival.value.oid), (SmiLPOID)&smival.value.oid);
132   }
133 }
134
135
136 //=============[Oid::Oid(const unsigned long *raw_oid, int oid_len) ]====
137 // constructor using raw numeric form
138 //
139 // copy the integer values into the private member
140 Oid::Oid(const unsigned long *raw_oid, int oid_len)
141   : iv_str(0), iv_part_str(0), m_changed(true)
142 {
143   smival.syntax = sNMP_SYNTAX_OID;
144   smival.value.oid.len = 0;
145   smival.value.oid.ptr = 0;
146
147   if (raw_oid && (oid_len > 0))
148   {
149     smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid_len];
150     if (smival.value.oid.ptr)
151     {
152       smival.value.oid.len = oid_len;
153       for (int i=0; i < oid_len; i++)
154         smival.value.oid.ptr[i] = raw_oid[i];
155     }
156   }
157 }
158
159 //=============[Oid::~Oid]==============================================
160 Oid::~Oid()
161 {
162   delete_oid_ptr();
163   if (iv_str)      delete [] iv_str;        // free up the output string
164   if (iv_part_str) delete [] iv_part_str;   // free up the output string
165 }
166
167
168 //=============[Oid::operator = const char * dotted_string ]==============
169 // assignment to a string operator overloaded
170 //
171 // free the existing oid
172 // create the new oid from the string
173 // return this object
174 Oid& Oid::operator=(const char *dotted_oid_string)
175 {
176   delete_oid_ptr();
177
178   // assign the new value
179   StrToOid(dotted_oid_string, &smival.value.oid);
180   return *this;
181 }
182
183
184 //=============[Oid:: operator = const Oid &oid ]==========================
185 // assignment to another oid object overloaded
186 //
187 // free the existing oid
188 // create a new one from the object passed in
189 Oid& Oid::operator=(const Oid &oid)
190 {
191   if (this == &oid) return *this;  // protect against assignment from self
192
193   delete_oid_ptr();
194
195   // check for zero len on source
196   if (oid.smival.value.oid.len == 0)
197     return *this;
198
199   // allocate some memory for the oid
200   smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid.smival.value.oid.len];
201   if (smival.value.oid.ptr)
202     OidCopy((SmiLPOID)&(oid.smival.value.oid), (SmiLPOID)&smival.value.oid);
203   return *this;
204 }
205
206
207 //==============[Oid:: operator += const char *a ]=========================
208 // append operator, appends a string
209 //
210 // allocate some space for a max oid string
211 // extract current string into space
212 // concat new string
213 // free up existing oid
214 // make a new oid from string
215 // delete allocated space
216 Oid& Oid::operator+=(const char *a)
217 {
218   unsigned int n;
219
220   if (!a) return *this;
221
222   if (*a == '.') ++a;
223
224   n = (smival.value.oid.len * SNMPCHARSIZE) + (smival.value.oid.len)
225        + 1 + SAFE_UINT_CAST(strlen(a));
226   char *ptr = new char[n];
227   if (ptr)
228   {
229     /// @todo optimze this function (avoid conversion to string)
230     OidToStr(&smival.value.oid, n, ptr);
231     if (ptr[0])
232       STRCAT(ptr,".");
233     STRCAT(ptr,a);
234
235     delete_oid_ptr();
236
237     StrToOid(ptr, &smival.value.oid);
238     delete [] ptr;
239   }
240   return *this;
241 }
242
243 //=============[ int operator == oid,oid ]=================================
244 // equivlence operator overloaded
245 int operator==(const Oid &lhs, const Oid &rhs)
246 {
247   // ensure same len, then use nCompare
248   if (rhs.len() != lhs.len()) return 0;
249   return (lhs.nCompare(rhs.len(), rhs) == 0);
250 }
251
252 //==============[ operator<(Oid &x,Oid &y) ]=============================
253 // less than < overloaded
254 int operator<(const Oid &lhs, const Oid &rhs)
255 {
256   int result;
257   // call nCompare with the current
258   // Oidx, Oidy and len of Oidx
259   if((result = lhs.nCompare(rhs.len(), rhs))<0)  return 1;
260   if (result > 0)    return 0;
261
262   // if here, equivalent substrings, call the shorter one <
263   return (lhs.len() < rhs.len());
264 }
265
266 //==============[ operator==(Oid &x,char *) ]=============================
267 // equivlence operator overloaded
268 int operator==(const Oid &x, const char *dotted_oid_string)
269 {
270   Oid to(dotted_oid_string);   // create a temp oid object
271   return (x == to);   // compare using existing operator
272 }
273
274 //==============[ operator!=(Oid &x,char*) ]=============================
275 // not equivlence operator overloaded
276 int operator!=(const Oid &x, const char *dotted_oid_string)
277 {
278   Oid to(dotted_oid_string);  // create a temp oid object
279   return (x != to);  // compare using existing operator
280 }
281
282 //==============[ operator<(Oid &x,char*) ]=============================
283 // less than < operator overloaded
284 int operator<(const Oid &x, const char *dotted_oid_string)
285 {
286   Oid to(dotted_oid_string);  // create a temp oid object
287   return (x < to);  // compare using existing operator
288 }
289
290 //==============[ operator<=(Oid &x,char *) ]=============================
291 // less than <= operator overloaded
292 int operator<=(const Oid &x,char *dotted_oid_string)
293 {
294   Oid to(dotted_oid_string);  // create a temp oid object
295   return (x <= to);  // compare using existing operator
296 }
297
298 //==============[ operator>(Oid &x,char* ]=============================
299 // greater than > operator overloaded
300 int operator>(const Oid &x,const char *dotted_oid_string)
301 {
302   Oid to(dotted_oid_string);  // create a temp oid object
303   return (x > to);   // compare using existing operator
304 }
305
306 //==============[ operator>=(Oid &x,char*) ]=============================
307 // greater than >= operator overloaded
308 int operator>=(const Oid &x,const char *dotted_oid_string)
309 {
310   Oid to(dotted_oid_string);  // create a temp oid object
311   return (x >= to);   // compare using existing operator
312 }
313
314 //===============[Oid::set_data ]==---=====================================
315 // copy data from raw form...
316 void Oid::set_data(const unsigned long *raw_oid,
317                    const unsigned int oid_len)
318 {
319   if (smival.value.oid.len < oid_len)
320   {
321     delete_oid_ptr();
322
323     smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid_len];
324     if (!smival.value.oid.ptr) return;
325   }
326   MEMCPY((SmiLPBYTE) smival.value.oid.ptr,
327          (SmiLPBYTE) raw_oid,
328          (size_t) (oid_len*sizeof(SmiUINT32)));
329   smival.value.oid.len = oid_len;
330   m_changed = true;
331 }
332
333 // Set the data from raw form.
334 void Oid::set_data(const char *str, const unsigned int str_len)
335 {
336   if (smival.value.oid.len < str_len)
337   {
338     delete_oid_ptr();
339
340     smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[str_len];
341     if (!smival.value.oid.ptr) return;
342   }
343
344   if ((!str) || (str_len == 0))
345     return;
346
347   for (unsigned int i=0; i<str_len; i++)
348     smival.value.oid.ptr[i] = str[i];
349
350   smival.value.oid.len = str_len;
351   m_changed = true;
352 }
353
354 //===============[Oid::trim(unsigned int) ]============================
355 // trim off the n leftmost values of an oid
356 // Note!, does not adjust actual space for
357 // speed
358 void Oid::trim(const unsigned long n)
359 {
360   // verify that n is legal
361   if ((n <= smival.value.oid.len) && (n > 0))
362   {
363     smival.value.oid.len -= n;
364     if (smival.value.oid.len == 0)
365       delete_oid_ptr();
366     m_changed = true;
367   }
368 }
369
370 //===============[Oid::operator += const unsigned int) ]====================
371 // append operator, appends an int
372 //
373 Oid& Oid::operator+=(const unsigned long i)
374 {
375   Oid other(&i, 1);
376   (*this) += other;
377   return *this;
378 }
379
380 //===============[Oid::operator += const Oid) ]========================
381 // append operator, appends an Oid
382 //
383 // allocate some space for a max oid string
384 // extract current string into space
385 // concat new string
386 // free up existing oid
387 // make a new oid from string
388 // delete allocated space
389 Oid& Oid::operator+=(const Oid &o)
390 {
391   SmiLPUINT32 new_oid;
392
393   if (o.smival.value.oid.len == 0)
394     return *this;
395
396   new_oid = (SmiLPUINT32) new unsigned long[smival.value.oid.len + o.smival.value.oid.len];
397   if (new_oid == 0)
398   {
399     delete_oid_ptr();
400     return *this;
401   }
402
403   if (smival.value.oid.ptr)
404   {
405     MEMCPY((SmiLPBYTE) new_oid,
406            (SmiLPBYTE) smival.value.oid.ptr,
407            (size_t) (smival.value.oid.len*sizeof(SmiUINT32)));
408
409     delete [] smival.value.oid.ptr;
410   }
411
412   // out with the old, in with the new...
413   smival.value.oid.ptr = new_oid;
414
415   MEMCPY((SmiLPBYTE) &new_oid[smival.value.oid.len],
416          (SmiLPBYTE) o.smival.value.oid.ptr,
417          (size_t) (o.smival.value.oid.len*sizeof(SmiUINT32)));
418
419   smival.value.oid.len += o.smival.value.oid.len;
420
421   m_changed = true;
422   return *this;
423 }
424
425 //==============[Oid::get_printable(unsigned int start, n) ]=============
426 // return a dotted string starting at start,
427 // going n positions to the left
428 // NOTE, start is 1 based (the first id is at position #1)
429 const char *Oid::get_printable(const unsigned long start,
430                                const unsigned long n,
431                                char *&buffer) const
432 {
433   if (!m_changed && (buffer == iv_str))  return buffer;
434
435   unsigned long nz;
436   unsigned long my_start = start - 1;
437   unsigned long my_end   = my_start + n;
438
439   nz = (smival.value.oid.len * (SNMPCHARSIZE + 1)) + 1;
440
441   if (buffer) delete [] buffer;  // delete the previous output string
442
443   buffer = new char[nz];  // allocate some space for the output string
444   if (buffer == 0)
445     return 0;
446
447   buffer[0] = 0;  // init the string
448
449   // cannot ask for more than there is..
450   if ((start == 0) || (my_end > smival.value.oid.len))
451     return buffer;
452
453   char *cur_ptr = buffer;
454   bool first = true;
455
456   // loop through and build up a string
457   for (unsigned long index = my_start; index < my_end; ++index)
458   {
459     // if not at begin, pad with a dot
460     if (first)
461       first = false;
462     else
463       *cur_ptr++ = '.';
464
465     // convert data element to a string
466     cur_ptr += sprintf(cur_ptr, "%lu", smival.value.oid.ptr[index]);
467   }
468
469   if (buffer == iv_str)
470   {
471     Oid *nc_this = PP_CONST_CAST(Oid*, this);
472     nc_this->m_changed = false;
473   }
474
475   return buffer;
476 }
477
478
479 //=============[Oid::StrToOid(char *string, SmiLPOID dst) ]==============
480 // convert a string to an oid
481 int Oid::StrToOid(const char *str, SmiLPOID dstOid) const
482 {
483   unsigned int index = 0;
484
485   // make a temp buffer to copy the data into first
486   SmiLPUINT32 temp;
487   unsigned int nz;
488
489   if (str && *str)
490   {
491     nz = SAFE_UINT_CAST(strlen(str));
492   }
493   else
494   {
495     dstOid->len = 0;
496     dstOid->ptr = 0;
497     return -1;
498   }
499   temp = (SmiLPUINT32) new unsigned long[nz];
500
501   if (temp == 0) return -1;   // return if can't get the mem
502
503   while ((*str) && (index < nz))
504   {
505     // skip over the dot
506     if (*str == '.') ++str;
507
508     // convert digits
509     if (my_isdigit(*str))
510     {
511       unsigned long number = 0;
512
513       // grab a digit token and convert it to a long int
514       while (my_isdigit(*str))
515         number = (number * 10) + *(str++) - '0';
516
517       // stuff the value into the array and bump the counter
518       temp[index++] = number;
519
520       // there must be a dot or end of string now
521       if ((*str) && (*str != '.'))
522       {
523         delete [] temp;
524         return -1;
525       }
526     }
527
528     // check for other chars
529     if ((*str) && (*str != '.'))
530     {
531       // found String -> converting it into an oid
532       if (*str != '$')
533       {
534         delete [] temp;
535         return -1;
536       }
537
538       // skip $
539       ++str;
540
541       // copy until second $
542       while ((*str) && (*str != '$'))
543       {
544         temp[index] = (unsigned char)*str;
545         ++str;
546         ++index;
547       }
548
549       if (*str != '$')
550       {
551         delete [] temp;
552         return -1;
553       }
554
555       // skip over the $
556       ++str;
557
558       // there must be a dot or end of string now
559       if ((*str) && (*str != '.'))
560       {
561         delete [] temp;
562         return -1;
563       }
564     }
565   }
566
567   // get some space for the real oid
568   dstOid->ptr = (SmiLPUINT32) new unsigned long[index];
569   // return if can't get the mem needed
570   if(dstOid->ptr == 0)
571   {
572     delete [] temp;
573     return -1;
574   }
575
576   // copy in the temp data
577   MEMCPY((SmiLPBYTE) dstOid->ptr,
578          (SmiLPBYTE) temp,
579          (size_t) (index*sizeof(SmiUINT32)));
580
581   // set the len of the oid
582   dstOid->len = index;
583
584   // free up temp data
585   delete [] temp;
586
587   return (int) index;
588 }
589
590
591 //===============[Oid::OidCopy(source, destination) ]====================
592 // Copy an oid
593 int Oid::OidCopy(SmiLPOID srcOid, SmiLPOID dstOid) const
594 {
595   // check source len ! zero
596   if (srcOid->len == 0) return -1;
597
598   // copy source to destination
599   MEMCPY((SmiLPBYTE) dstOid->ptr,
600          (SmiLPBYTE) srcOid->ptr,
601          (size_t) (srcOid->len*sizeof(SmiUINT32)));
602
603   //set the new len
604   dstOid->len = srcOid->len;
605   return (int) srcOid->len;
606 }
607
608
609 //===============[Oid::nCompare(n, Oid) ]=================================
610 // compare the n leftmost values of two oids (left-to_right )
611 //
612 // self == Oid then return 0, they are equal
613 // self < Oid then return -1, <
614 // self > Oid then return 1,  >
615 int Oid::nCompare(const unsigned long n,
616                   const Oid &o) const
617 {
618   unsigned long length = n;
619   bool reduced_len = false;
620
621   // If both oids are too short, decrease len
622   while ((smival.value.oid.len < length) && (o.smival.value.oid.len < length))
623     length--;
624
625   if (length == 0) return 0; // equal
626     
627   // only compare for the minimal length
628   if (length > smival.value.oid.len)
629   {
630     length = smival.value.oid.len;
631     reduced_len = true;
632   }
633   if (length > o.smival.value.oid.len)
634   {
635     length = o.smival.value.oid.len;
636     reduced_len = true;
637   }
638
639   unsigned long z = 0;
640   while (z < length)
641   {
642     if (smival.value.oid.ptr[z] < o.smival.value.oid.ptr[z])
643       return -1;                              // less than
644     if (smival.value.oid.ptr[z] > o.smival.value.oid.ptr[z])
645       return 1;                               // greater than
646     ++z;
647   }
648
649   // if we truncated the len then these may not be equal
650   if (reduced_len)
651   {
652     if (smival.value.oid.len < o.smival.value.oid.len) return -1;
653     if (smival.value.oid.len > o.smival.value.oid.len) return 1;
654   }
655   return 0;                                 // equal
656 }
657
658 //================[Oid::OidToStr ]=========================================
659 // convert an oid to a string
660 int Oid::OidToStr(const SmiOID *srcOid,
661                   SmiUINT32 size,
662                   char *str) const
663 {
664   unsigned totLen = 0;
665   char szNumber[SNMPBUFFSIZE];
666   int cur_len;
667
668   str[0] = 0;   // init the string
669
670   // verify there is something to copy
671   if (srcOid->len == 0)
672     return -1;
673
674   // loop through and build up a string
675   for (unsigned long index = 0; index < srcOid->len; ++index)
676   {
677     // convert data element to a string
678     cur_len = sprintf(szNumber, "%lu", srcOid->ptr[index]);
679
680     // verify len is not over
681     if (totLen + cur_len + 1 >= size)
682       return -2;
683
684     // if not at begin, pad with a dot
685     if (totLen)
686       str[totLen++] = '.';
687
688     // copy the string token into the main string
689     STRCPY(str + totLen, szNumber);
690
691     // adjust the total len
692     totLen += cur_len;
693   }
694   return totLen+1;
695 }
696
697
698 //================[ general Value = operator ]========================
699 SnmpSyntax& Oid::operator=(const SnmpSyntax &val)
700 {
701   if (this == &val) return *this; // protect against assignment from self
702
703   delete_oid_ptr();
704
705   // assign new value
706   if (val.valid())
707   {
708     switch (val.get_syntax())
709     {
710       case sNMP_SYNTAX_OID:
711         set_data(((Oid &)val).smival.value.oid.ptr,
712                   (unsigned int)((Oid &)val).smival.value.oid.len);
713         break;
714     }
715   }
716   return *this;
717 }
718
719 int Oid::get_asn1_length() const
720 {
721   int length = 1; // for first 2 subids
722
723   for (unsigned int i = 2; i < smival.value.oid.len; ++i)
724   {
725     unsigned long v = smival.value.oid.ptr[i];
726
727     if      (v <       0x80) //  7 bits long subid 
728       length += 1;
729     else if (v <     0x4000) // 14 bits long subid
730       length += 2;
731     else if (v <   0x200000) // 21 bits long subid
732       length += 3;
733     else if (v < 0x10000000) // 28 bits long subid
734       length += 4;
735     else                     // 32 bits long subid
736       length += 5;
737   }
738
739   if (length < 128)
740     return length + 2;
741   else if (length < 256)
742     return length + 3;
743   return length + 4;
744 }
745
746 #ifdef SNMP_PP_NAMESPACE
747 }; // end of namespace Snmp_pp
748 #endif