2 //=============================================================================
6 * This module contains the implementation of the oid class. This
7 * includes all protected and public member functions. The oid class
8 * may be compiled stand alone without the use of any other library.
10 * @author Peter E MellquistMichael R MacFaden mrm@cisco.com - rework & ACE port
12 //=============================================================================
14 /*===================================================================
16 Hewlett-Packard Company
18 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
19 Permission to use, copy, modify, distribute and/or sell this software
20 and/or its documentation is hereby granted without fee. User agrees
21 to display the above copyright notice and this license notice in all
22 copies of the software and any documentation of the software. User
23 agrees to assume all liability for the use of the software; Hewlett-Packard
24 makes no representations about the suitability of this software for any
25 purpose. It is provided "AS-IS" without warranty of any kind,either express
26 or implied. User hereby grants a royalty-free license to any and all
27 derivatives based upon this software code base.
28 =====================================================================*/
30 //---------[ external C libraries used ]--------------------------------
32 #include "asnmp/oid.h" // include def for oid class
33 #include "ace/OS_NS_string.h"
34 #include "ace/OS_NS_stdio.h"
35 #include "ace/OS_Memory.h"
36 #include "ace/OS_NS_ctype.h"
38 enum Defs
{SNMPBUFFSIZE
=300,
39 SNMPCHARSIZE
=15}; // max oid value (4294967295UL)
41 #define NO_MEM_STR "ERROR: Oid::to_string: memory allocation failure"
43 //=============[Oid::get_syntax()]====================================
44 SmiUINT32
Oid::get_syntax()
46 return sNMP_SYNTAX_OID
;
50 //=============[Oid::Oid( const char *dotted_string ]=====================
51 // constructor using a dotted string
53 // do a string to oid using the string passed in
54 Oid::Oid( const char * dotted_oid_string
, size_t size
)
56 // can't init enum SmiValue so just memset it clean
60 if ((z
= ACE_OS::strlen(dotted_oid_string
)) == 0) {
65 if (size
== (unsigned int)-1)
70 char *ptr
= (char *)dotted_oid_string
;;
72 // create new buffer if needed
73 ACE_NEW(ptr
, char [size
]);
75 // sz should be in StrToOid?
76 ACE_OS::memcpy( (void *)ptr
, dotted_oid_string
, size
);
80 if (StrToOid( (char *) ptr
, &smival
.value
.oid
, byte_counter
) < 0)
82 if (ptr
!= dotted_oid_string
)
87 //=============[Oid::Oid( const Oid &oid) ]================================
88 // constructor using another oid object
90 // do an oid copy using the oid object passed in
91 Oid::Oid ( const Oid
&oid
)
96 // allocate some memory for the oid
97 // in this case the size to allocate is the same
98 // size as the source oid
99 if (oid
.smival
.value
.oid
.len
) {
100 ACE_NEW(smival
.value
.oid
.ptr
, SmiUINT32
[ oid
.smival
.value
.oid
.len
]);
102 OidCopy( (SmiLPOID
) &(oid
.smival
.value
.oid
),(SmiLPOID
)
103 &smival
.value
.oid
, byte_counter
);
108 //=============[Oid::Oid( const unsigned long *raw_oid, int oid_len) ]====
109 // constructor using raw numeric form
111 // copy the integer values into the private member
112 Oid::Oid(const unsigned long *raw_oid
, size_t oid_len
)
116 smival
.syntax
= sNMP_SYNTAX_OID
;
119 if (raw_oid
&& oid_len
> 0) {
120 ACE_NEW(smival
.value
.oid
.ptr
, SmiUINT32
[ oid_len
]);
121 smival
.value
.oid
.len
= oid_len
;
122 for (size_t i
=0; i
< oid_len
; i
++)
123 smival
.value
.oid
.ptr
[i
] = raw_oid
[i
];
127 //=============[Oid::~Oid]==============================================
130 // free up the descriptor space
133 // free up the octet deep memory
134 if ( smival
.value
.oid
.ptr
) {
138 // free up the output string
144 //=============[Oid::operator = const char * dotted_string ]==============
145 // assignment to a string operator overloaded
147 // free the existing oid
148 // create the new oid from the string
149 // return this object
150 void Oid::set_data( const char *dotted_oid_string
)
152 // delete the old value
153 if ( smival
.value
.oid
.ptr
) {
157 // assign the new value
159 if (StrToOid( (char *) dotted_oid_string
, &smival
.value
.oid
, byte_counter
) <0)
164 //=============[Oid:: operator = const Oid &oid ]==========================
165 // assignment to another oid object overloaded
167 // free the existing oid
168 // create a new one from the object passed in
169 // TODO: measure perf vs memory of no realloc in case where len >= oid.len
170 Oid
& Oid::operator=( const Oid
&oid
)
172 // protect against assignment from self
178 // check for zero len on source
179 if ( oid
.smival
.value
.oid
.len
== 0)
182 const SmiLPOID srcOid
= (SmiLPOID
) &(oid
.smival
.value
.oid
);
183 init_value(srcOid
, oid
.smival
.value
.oid
.len
);
187 // assign this object the oid, set to invalid if copy fails
188 void Oid::init_value(const SmiLPOID srcOid
, size_t len
)
190 // allocate some memory for the oid
191 ACE_NEW(smival
.value
.oid
.ptr
, SmiUINT32
[ len
]);
193 OidCopy( srcOid
, (SmiLPOID
) &smival
.value
.oid
, byte_counter
);
196 void Oid::init_value(const unsigned long *raw_oid
, size_t oid_len
)
198 if (smival
.value
.oid
.ptr
)
199 delete [] smival
.value
.oid
.ptr
;
201 ACE_NEW(smival
.value
.oid
.ptr
, SmiUINT32
[ oid_len
]);
202 ACE_OS::memcpy((SmiLPBYTE
) smival
.value
.oid
.ptr
,
204 (size_t) (oid_len
* sizeof(SmiUINT32
)));
205 smival
.value
.oid
.len
= oid_len
;
208 //==============[Oid:: operator += const char *a ]=========================
209 // append operator, appends a string
211 // allocate some space for a max oid string
212 // extract current string into space
214 // free up existing oid
215 // make a new oid from string
216 // delete allocated space
217 Oid
& Oid::operator+=( const char *a
)
226 size_t sz
= ACE_OS::strlen(a
);
229 n
= (smival
.value
.oid
.len
*SNMPCHARSIZE
) + smival
.value
.oid
.len
+ 1 + sz
;
231 ACE_NEW_RETURN(ptr
, char[ n
], *this);
233 if (OidToStr(&smival
.value
.oid
, n
,ptr
, byte_counter
) > 0) {
239 if (ACE_OS::strlen(ptr
))
240 ACE_OS::strcat(ptr
,".");
241 ACE_OS::strcat(ptr
,a
);
242 if ( smival
.value
.oid
.len
!=0) {
246 if (StrToOid( (char *) ptr
, &smival
.value
.oid
, byte_counter
) < 0) {
253 if (StrToOid( (char *) a
, &smival
.value
.oid
, byte_counter
) < 0) {
261 //=============[ bool operator == oid,oid ]=================================
262 // equivlence operator overloaded
263 bool operator==( const Oid
&lhs
, const Oid
&rhs
)
265 // ensure same len, then use left_comparison
266 if (rhs
.length() != lhs
.length())
268 if( lhs
.left_comparison( rhs
.length(), rhs
) == 0)
274 //==============[ bool operator!=( Oid &x,Oid &y) ]=======================
275 //not equivlence operator overloaded
276 bool operator!=( const Oid
&lhs
,const Oid
&rhs
)
278 return (!(lhs
== rhs
));
281 //==============[ bool operator<( Oid &x,Oid &y) ]========================
282 // less than < overloaded
283 bool operator<( const Oid
&lhs
,const Oid
&rhs
)
287 // call left_comparison with the current
288 // Oidx, Oidy and len of Oidx
289 if ((result
= lhs
.left_comparison( rhs
.length(), rhs
)) < 0)
295 // if here, equivalent substrings, call the shorter one <
296 if (lhs
.length() < rhs
.length())
303 //==============[ bool operator<=( Oid &x,Oid &y) ]=======================
304 // less than <= overloaded
305 bool operator<=( const Oid
&x
,const Oid
&y
)
307 if ( (x
< y
) || (x
== y
) )
313 //==============[ bool operator>( Oid &x,Oid &y) ]========================
314 // greater than > overloaded
315 bool operator>( const Oid
&x
,const Oid
&y
)
317 // just invert existing <=
324 //==============[ bool operator>=( Oid &x,Oid &y) ]=======================
325 // greater than >= overloaded
326 bool operator>=( const Oid
&x
,const Oid
&y
)
328 // just invert existing <
335 //===============[Oid::oidval ]=============================================
336 // return the WinSnmp oid part
337 SmiLPOID
Oid::oidval()
339 return (SmiLPOID
) &smival
.value
.oid
;
342 //===============[Oid::set_data ]==---=====================================
343 // copy data from raw form...
344 void Oid::set_data( const unsigned long *raw_oid
, const size_t oid_len
)
346 if (smival
.value
.oid
.len
< oid_len
) {
347 if ( smival
.value
.oid
.ptr
) {
351 init_value(raw_oid
, oid_len
);
355 //===============[Oid::len ]================================================
356 // return the len of the oid
357 size_t Oid::length() const
359 return smival
.value
.oid
.len
;
362 //===============[Oid::trim( unsigned int) ]============================
363 // trim off the n leftmost values of an oid
364 // Note!, does not adjust actual space for
366 void Oid::trim( const size_t n
)
368 // verify that n is legal
369 if ((n
<=smival
.value
.oid
.len
)&&(n
>0)) {
370 smival
.value
.oid
.len
-= n
;
372 if (smival
.value
.oid
.len
== 0) {
378 //===============[Oid::set_invalid() ]====================
379 // make this object invalid by resetting all values
380 void Oid::set_invalid() {
381 delete [] smival
.value
.oid
.ptr
;
382 smival
.value
.oid
.ptr
= 0;
383 smival
.value
.oid
.len
= 0;
388 //===============[Oid::set_null() ]====================
389 void Oid::set_null() {
390 smival
.syntax
= sNMP_SYNTAX_OID
;
391 smival
.value
.oid
.ptr
= 0;
392 smival
.value
.oid
.len
= 0;
396 //===============[Oid::operator += const unsigned int) ]====================
397 // append operator, appends an int
399 // allocate some space for a max oid string
400 // extract current string into space
402 // free up existing oid
403 // make a new oid from string
404 // delete allocated space
405 Oid
& Oid::operator+=( const unsigned long i
)
407 unsigned long n
= (smival
.value
.oid
.len
* SNMPCHARSIZE
)
408 + ( smival
.value
.oid
.len
-1) + 1 + 4;
409 char buffer
[SNMPBUFFSIZE
];
411 // two cases: null oid, existing oid
413 // allocate some temporary space
415 ACE_NEW_RETURN(ptr
, char[ n
], *this);
417 if (OidToStr(&smival
.value
.oid
, n
, ptr
, byte_counter
) < 0) {
423 if (ACE_OS::strlen(ptr
))
424 ACE_OS::strcat(ptr
,".");
426 if (ACE_OS::sprintf( buffer
,"%lu",i
) != -1) {
427 ACE_OS::strcat(ptr
, buffer
);
428 if ( smival
.value
.oid
.ptr
) {
431 if (StrToOid( (char *) ptr
, &smival
.value
.oid
, byte_counter
) < 0) {
438 init_value((const unsigned long *)&i
, (size_t)1);
444 //===============[Oid::operator += const Oid) ]========================
445 // append operator, appends an Oid
447 // allocate some space for a max oid string
448 // extract current string into space
450 // free up existing oid
451 // make a new oid from string
452 // delete allocated space
453 Oid
& Oid::operator+=( const Oid
&o
)
457 if (o
.smival
.value
.oid
.len
== 0)
460 ACE_NEW_RETURN(new_oid
,
461 SmiUINT32
[ smival
.value
.oid
.len
+ o
.smival
.value
.oid
.len
], *this);
462 if (smival
.value
.oid
.ptr
) {
463 ACE_OS::memcpy((SmiLPBYTE
) new_oid
,
464 (SmiLPBYTE
) smival
.value
.oid
.ptr
,
465 (size_t) (smival
.value
.oid
.len
*sizeof(SmiUINT32
)));
467 delete [] smival
.value
.oid
.ptr
;
470 // out with the old, in with the new...
471 smival
.value
.oid
.ptr
= new_oid
;
473 ACE_OS::memcpy((SmiLPBYTE
) &new_oid
[smival
.value
.oid
.len
],
474 (SmiLPBYTE
) o
.smival
.value
.oid
.ptr
,
475 (size_t) (o
.smival
.value
.oid
.len
*sizeof(SmiUINT32
)));
477 smival
.value
.oid
.len
+= o
.smival
.value
.oid
.len
;
481 // return string portion of the oid
483 const char * Oid::to_string()
487 return ""; // be consistent with other classes
489 // the worst case char len of an oid can be..
490 // oid.len*3 + dots in between if each oid is XXXX
491 // so.. size = (len*4) + (len-1) + 1 , extra for a null
493 n
= (smival
.value
.oid
.len
*SNMPCHARSIZE
) + ( smival
.value
.oid
.len
-1) + 1 ;
495 n
= 1; // need at least 1 byte for a null string
497 // adjust the len of output array in case size was adjusted
500 // allocate some space for the output string
501 ACE_NEW_RETURN(iv_str
, char[ n
], "");
503 // convert to an output string
505 if ( valid() && iv_str
!= 0)
506 if (OidToStr(&smival
.value
.oid
,n
,iv_str
, how_many
) < 0)
507 return "ERROR: Oid::OidToStr failed";
511 //==============[Oid::suboid( unsigned int start, n) ]=============
512 int Oid::suboid(Oid
& new_oid
, size_t start
, size_t how_many
)
517 if (how_many
== (size_t)-1)
520 if (how_many
> length())
524 new_oid
.set_invalid();
526 size_t new_size
= how_many
- start
;
529 new_oid
.smival
.value
.oid
.len
= new_size
;
530 ACE_NEW_RETURN(new_oid
.smival
.value
.oid
.ptr
,
531 SmiUINT32
[ new_oid
.smival
.value
.oid
.len
], -1);
532 // copy source to destination
533 ACE_OS::memcpy( (SmiLPBYTE
) new_oid
.smival
.value
.oid
.ptr
,
534 (SmiLPBYTE
) (smival
.value
.oid
.ptr
+ start
),
535 new_size
* sizeof(SmiLPBYTE
));
540 //=============[Oid::StrToOid( char *string, SmiLPOID dst) ]==============
541 // convert a string to an oid
542 int Oid::StrToOid( const char *string
, SmiLPOID dstOid
, size_t& how_many
)
547 // make a temp buffer to copy the data into first
551 if (string
&& *string
) {
552 nz
= ACE_OS::strlen( string
);
560 ACE_NEW_RETURN(temp
, SmiUINT32
[ nz
], -1);
561 while (*string
!=0 && index
<nz
) {
562 // init the number for each token
568 // grab a digit token and convert it to a long int
569 while (ACE_OS::ace_isdigit(*string
))
570 number
=number
*10 + *(string
++)-'0';
572 // check for invalid chars
573 if (*string
!=0 && *string
!='.') {
574 // Error: Invalid character in string
579 // stuff the value into the array
580 temp
[index
] = number
;
581 index
++; // bump the counter
585 // get some space for the real oid
586 ACE_NEW_RETURN(dstOid
->ptr
, SmiUINT32
[ index
], -1);
587 // TODO: make tmp autoptr type delete [] temp to prevent leak
589 // copy in the temp data
590 ACE_OS::memcpy((SmiLPBYTE
) dstOid
->ptr
, (SmiLPBYTE
) temp
,
591 (size_t) (index
*sizeof(SmiUINT32
)));
593 // set the len of the oid
604 //===============[Oid::OidCopy( source, destination) ]====================
605 // Copy an oid, return bytes copied
606 int Oid::OidCopy( SmiLPOID srcOid
, SmiLPOID dstOid
, size_t& how_many_bytes
)
608 // check source len ! zero
609 if (srcOid
->len
== 0)
612 // copy source to destination
613 ACE_OS::memcpy((SmiLPBYTE
) dstOid
->ptr
,
614 (SmiLPBYTE
) srcOid
->ptr
,
615 (size_t) (srcOid
->len
* sizeof(SmiUINT32
)));
618 dstOid
->len
= srcOid
->len
;
619 how_many_bytes
= srcOid
->len
;
625 //===============[Oid::left_comparison( n, Oid) ]=================================
626 // compare the n leftmost values of two oids ( left-to_right )
628 // self == Oid then return 0, they are equal
629 // self < Oid then return -1, <
630 // self > Oid then return 1, >
631 int Oid::left_comparison( const unsigned long n
, const Oid
&o
) const
634 unsigned long len
= n
;
637 // 1st case they both are null
638 if (( len
==0)&&( this->smival
.value
.oid
.len
==0))
641 // verify that n is valid, must be >= 0
645 // only compare for the minimal length
646 if (len
> this->smival
.value
.oid
.len
) {
647 len
= this->smival
.value
.oid
.len
;
650 if (len
> o
.smival
.value
.oid
.len
) {
651 len
= o
.smival
.value
.oid
.len
;
657 if ( this->smival
.value
.oid
.ptr
[z
] < o
.smival
.value
.oid
.ptr
[z
])
658 return -1; // less than
659 if ( this->smival
.value
.oid
.ptr
[z
] > o
.smival
.value
.oid
.ptr
[z
])
660 return 1; // greater than
664 // if we truncated the len then these may not be equal
666 if (this->smival
.value
.oid
.len
< o
.smival
.value
.oid
.len
)
668 if (this->smival
.value
.oid
.len
> o
.smival
.value
.oid
.len
)
676 //===============[Oid::left_comparison( n, Oid) ]=================================
677 // compare the n rightmost bytes (right-to-left)
681 int Oid::right_comparison( const unsigned long n
, const Oid
&o
) const
683 // oid to compare must have at least the same number
684 // of sub-ids to comparison else the argument Oid is
689 // also can't compare argument oid for sub-ids which
690 // THIS does not have
691 if ( this->length() < n
)
694 int start
= (int) this->length();
695 int end
= (int) start
- (int) n
;
696 for ( int z
=start
;z
< end
;z
--)
698 if ( o
.smival
.value
.oid
.ptr
[z
] < this->smival
.value
.oid
.ptr
[z
])
700 if ( o
.smival
.value
.oid
.ptr
[z
] > this->smival
.value
.oid
.ptr
[z
])
704 return 0; // they are equal
709 //================[ Oid::valid() ]========================================
710 // is the Oid object valid
712 int Oid::valid() const
714 return ( smival
.value
.oid
.ptr
? 1 : 0 );
717 //================[Oid::OidToStr ]=========================================
718 // convert an oid to a string
719 int Oid::OidToStr( SmiLPOID srcOid
, unsigned long size
,
720 char *string
, size_t& how_many_bytes
)
722 unsigned long index
= 0;
724 char szNumber
[SNMPBUFFSIZE
];
729 // verify there is something to copy
730 if (srcOid
->len
== 0)
733 // loop through and build up a string
734 for (index
=0; index
< srcOid
->len
; index
++) {
735 // convert data element to a string
736 if (ACE_OS::sprintf( szNumber
,"%lu", srcOid
->ptr
[index
]) == -1)
739 // verify len is not over
740 if (totLen
+ ACE_OS::strlen(szNumber
) + 1 >= size
)
743 // if not at end, pad with a dot
745 string
[totLen
++] = '.';
747 // copy the string token into the main string
748 ACE_OS::strcpy(string
+ totLen
, szNumber
);
750 // adjust the total len
751 totLen
+= ACE_OS::strlen(szNumber
);
754 how_many_bytes
= totLen
+ 1;
759 //================[ general Value = operator ]========================
760 SnmpSyntax
& Oid::operator=( SnmpSyntax
&val
)
762 // protect against assignment from self
766 // blow away old value
767 smival
.value
.oid
.len
= 0;
768 if (smival
.value
.oid
.ptr
) {
774 switch (val
.get_syntax()) {
775 case sNMP_SYNTAX_OID
:
776 set_data( ((Oid
&)val
).smival
.value
.oid
.ptr
,
777 (unsigned int)((Oid
&)val
).smival
.value
.oid
.len
);
784 //================[ [] operator ]=====================================
785 unsigned long& Oid::operator[](size_t position
)
787 return smival
.value
.oid
.ptr
[position
];
790 //================[ clone ]===========================================
791 SnmpSyntax
*Oid::clone() const
793 return (SnmpSyntax
*) new Oid(*this);