Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ASNMP / asnmp / asn1.cpp
blobe5c8ad90171c7d287b0dc9a84e415f03d6aa3d9b
2 //=============================================================================
3 /**
4 * @file asn1.cpp
6 * The Vb class is an encapsulation of the snmp variable binding.
7 * This module contains the class definition for the variable binding (VB)
8 * class. The VB class is an encapsulation of a SNMP VB. A VB object is
9 * composed of one SNMP++ Oid and one SMI value. The Vb class utilizes Oid
10 * objects and thus requires the Oid class. To use this class,
11 * set oid, value then call valid() to be sure object was constructed correctly.
13 * @author S. Waldbusser (assumed)Michael R MacFaden mrm@cisco.com - rework & ACE port
15 //=============================================================================
17 /**********************************************************************
18 // *
19 * Abstract Syntax Notation One, ASN.1
20 * As defined in ISO/IS 8824 and ISO/IS 8825
21 * This implements a subset of the above International Standards that
22 * is sufficient to implement SNMP.
24 * Encodes abstract data types into a machine independent stream of bytes.
26 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
28 All Rights Reserved
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of CMU not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
45 ******************************************************************/
47 #include "asnmp/asn1.h"
48 #include "asnmp/snmp.h"
49 #include "ace/OS_NS_string.h"
50 #include "ace/Global_Macros.h"
53 * parse_int - pulls a long out of an ASN int type.
54 * On entry, datalength is input as the number of valid bytes following
55 * "data". On exit, it is returned as the number of valid bytes
56 * following the end of this object.
58 * Returns a pointer to the first byte past the end
59 * of this object (i.e. the start of the next object).
60 * Returns 0 on any error.
62 u_char * asn1::parse_int(u_char *data,
63 int *datalength,
64 u_char *type,
65 long int *intp,
66 int intsize)
68 ACE_TRACE("asn1::parse_int");
70 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
72 u_char *bufp = data;
73 u_long asn_length;
74 long value = 0;
76 if (intsize != (int) sizeof (long)){
77 ASNERROR("not long");
78 return 0;
80 *type = *bufp++;
81 bufp =asn1::parse_length(bufp, &asn_length);
82 if (bufp == 0){
83 ASNERROR("bad length");
84 return 0;
86 if ((int)(asn_length + (bufp - data)) > *datalength){
87 ASNERROR("overflow of message");
88 return 0;
90 if ((int)asn_length > intsize){
91 ASNERROR("I don't support such large integers");
92 return 0;
94 *datalength -= (int)asn_length + (bufp - data);
95 if (*bufp & 0x80)
96 value = -1; /* integer is negative */
97 while(asn_length--)
98 value = (value << 8) | *bufp++;
99 *intp = value;
100 return bufp;
105 * parse_unsigned_int - pulls an u_long out of an ASN int type.
106 * On entry, datalength is input as the number of valid bytes following
107 * "data". On exit, it is returned as the number of valid bytes
108 * following the end of this object.
110 * Returns a pointer to the first byte past the end
111 * of this object (i.e. the start of the next object).
112 * Returns 0 on any error.
114 u_char * asn1::parse_unsigned_int( u_char *data,
115 int *datalength,
116 u_char *type,
117 u_long *intp,
118 int intsize)
120 ACE_TRACE("asn1::parse_unsigned_int");
122 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
124 u_char *bufp = data;
125 u_long asn_length;
126 u_long value = 0;
128 if (intsize != (int) sizeof (long)){
129 ASNERROR("not long");
130 return 0;
132 *type = *bufp++;
133 bufp = asn1::parse_length(bufp, &asn_length);
134 if (bufp == 0){
135 ASNERROR("bad length");
136 return 0;
138 if ((int)(asn_length + (bufp - data)) > *datalength){
139 ASNERROR("overflow of message");
140 return 0;
142 if (((int)asn_length > (intsize + 1)) ||
143 (((int)asn_length == intsize + 1) && *bufp != 0x00)){
144 ASNERROR("I don't support such large integers");
145 return 0;
147 *datalength -= (int)asn_length + (bufp - data);
148 if (*bufp & 0x80)
149 value = (u_long) -1;
150 while(asn_length--)
151 value = (value << 8) | *bufp++;
152 *intp = value;
153 return bufp;
158 * build_int - builds an ASN object containing an integer.
159 * On entry, datalength is input as the number of valid bytes following
160 * "data". On exit, it is returned as the number of valid bytes
161 * following the end of this object.
163 * Returns a pointer to the first byte past the end
164 * of this object (i.e. the start of the next object).
165 * Returns 0 on any error.
167 u_char * asn1::build_int( u_char *data,
168 int *datalength,
169 u_char type,
170 long *intp,
171 int intsize)
173 ACE_TRACE("asn1::build_int");
175 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
178 long integer;
179 u_long mask;
181 if (intsize != (int) sizeof (long))
182 return 0;
183 integer = *intp;
185 * Truncate "unnecessary" bytes off of the most significant end of this
186 * 2's complement integer. There should be no sequence of 9
187 * consecutive 1's or 0's at the most significant end of the
188 * integer.
190 mask = u_long (0x1FF) << ((8 * (sizeof(u_long) - 1)) - 1);
191 /* mask is 0xFF800000 on a big-endian machine */
192 while((((integer & mask) == 0) || ((integer & mask) == mask))
193 && intsize > 1){
194 intsize--;
195 integer <<= 8;
197 data = asn1::build_header(data, datalength, type, intsize);
198 if (data == 0)
199 return 0;
200 if (*datalength < intsize)
201 return 0;
202 *datalength -= intsize;
203 mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1));
204 /* mask is 0xFF000000 on a big-endian machine */
205 while(intsize--){
206 *data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1)));
207 integer <<= 8;
209 return data;
214 * build_unsigned_int - builds an ASN object containing an integer.
215 * On entry, datalength is input as the number of valid bytes following
216 * "data". On exit, it is returned as the number of valid bytes
217 * following the end of this object.
219 * Returns a pointer to the first byte past the end
220 * of this object (i.e. the start of the next object).
221 * Returns 0 on any error.
223 u_char * asn1::build_unsigned_int( u_char *data,
224 int *datalength,
225 u_char type,
226 u_long *intp,
227 int intsize)
229 ACE_TRACE("asn1::build_unsigned_int");
231 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
234 u_long integer;
235 u_long mask;
236 int add_null_byte = 0;
238 if (intsize != (int) sizeof (long))
239 return 0;
240 integer = *intp;
241 mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1));
242 /* mask is 0xFF000000 on a big-endian machine */
243 if ((u_char)((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80){
244 /* if MSB is set */
245 add_null_byte = 1;
246 intsize++;
249 * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer.
250 * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the
251 * integer.
253 mask = u_long (0x1FF) << ((8 * (sizeof(u_long) - 1)) - 1);
254 /* mask is 0xFF800000 on a big-endian machine */
255 while((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1){
256 intsize--;
257 integer <<= 8;
259 data = asn1::build_header(data, datalength, type, intsize);
260 if (data == 0)
261 return 0;
262 if (*datalength < intsize)
263 return 0;
264 *datalength -= intsize;
265 if (add_null_byte == 1){
266 *data++ = '\0';
267 intsize--;
269 mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1));
270 /* mask is 0xFF000000 on a big-endian machine */
271 while(intsize--){
272 *data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1)));
273 integer <<= 8;
275 return data;
280 * parse_string - pulls an octet string out of an ASN octet string type.
281 * On entry, datalength is input as the number of valid bytes following
282 * "data". On exit, it is returned as the number of valid bytes
283 * following the beginning of the next object.
285 * "string" is filled with the octet string.
287 * Returns a pointer to the first byte past the end
288 * of this object (i.e. the start of the next object).
289 * Returns 0 on any error.
291 u_char * asn1::parse_string( u_char *data,
292 int *datalength,
293 u_char *type,
294 u_char *string,
295 int *strlength)
297 ACE_TRACE("asn1::parse_string");
299 * ASN.1 octet string ::= primstring | cmpdstring
300 * primstring ::= 0x04 asnlength byte {byte}*
301 * cmpdstring ::= 0x24 asnlength string {string}*
303 u_char *bufp = data;
304 u_long asn_length;
306 *type = *bufp++;
307 bufp = asn1::parse_length(bufp, &asn_length);
308 if (bufp == 0)
309 return 0;
310 if ((int)(asn_length + (bufp - data)) > *datalength){
311 ASNERROR("overflow of message");
312 return 0;
314 if ((int)asn_length > *strlength){
315 ASNERROR("I don't support such long strings");
316 return 0;
318 // fixed
319 ACE_OS::memcpy((char *)string, (char *)bufp, (int)asn_length);
320 *strlength = (int)asn_length;
321 *datalength -= (int)asn_length + (bufp - data);
322 return bufp + asn_length;
327 * build_string - Builds an ASN octet string object containing the input string.
328 * On entry, datalength is input as the number of valid bytes following
329 * "data". On exit, it is returned as the number of valid bytes
330 * following the beginning of the next object.
332 * Returns a pointer to the first byte past the end
333 * of this object (i.e. the start of the next object).
334 * Returns 0 on any error.
336 u_char * asn1::build_string( u_char *data,
337 int *datalength,
338 u_char type,
339 u_char *string,
340 int strlength)
342 ACE_TRACE("asn1::build_string");
344 * ASN.1 octet string ::= primstring | cmpdstring
345 * primstring ::= 0x04 asnlength byte {byte}*
346 * cmpdstring ::= 0x24 asnlength string {string}*
347 * This code will never send a compound string.
349 data = asn1::build_header(data, datalength, type, strlength);
350 if (data == 0)
351 return 0;
352 if (*datalength < strlength)
353 return 0;
354 // fixed
355 ACE_OS::memcpy((u_char *)data,(u_char *)string, strlength);
356 *datalength -= strlength;
357 return data + strlength;
362 * parse_header - interprets the ID and length of the current object.
363 * On entry, datalength is input as the number of valid bytes following
364 * "data". On exit, it is returned as the number of valid bytes
365 * in this object following the id and length.
367 * Returns a pointer to the first byte of the contents of this object.
368 * Returns 0 on any error.
370 u_char *asn1::parse_header( u_char *data,
371 int *datalength,
372 u_char *type)
374 ACE_TRACE("asn1::parse_header");
375 u_char *bufp = data;
376 int header_len;
377 u_long asn_length;
379 /* this only works on data types < 30, i.e. no extension octets */
380 if (IS_EXTENSION_ID(*bufp)){
381 ASNERROR("can't process ID >= 30");
382 return 0;
384 *type = *bufp;
385 bufp = asn1::parse_length(bufp + 1, &asn_length);
386 if (bufp == 0)
387 return 0;
388 header_len = bufp - data;
389 if ((int)(header_len + asn_length) > *datalength){
390 ASNERROR("asn length too long");
391 return 0;
393 *datalength = (int)asn_length;
394 return bufp;
398 * asn1::build_header - builds an ASN header for an object with the ID and
399 * length specified.
400 * On entry, datalength is input as the number of valid bytes following
401 * "data". On exit, it is returned as the number of valid bytes
402 * in this object following the id and length.
404 * This only works on data types < 30, i.e. no extension octets.
405 * The maximum length is 0xFFFF;
407 * Returns a pointer to the first byte of the contents of this object.
408 * Returns 0 on any error.
410 u_char * asn1::build_header( u_char *data,
411 int *datalength,
412 u_char type,
413 int length)
415 ACE_TRACE("asn1::build_header");
416 if (*datalength < 1)
417 return 0;
418 *data++ = type;
419 (*datalength)--;
420 return asn1::build_length(data, datalength, length);
424 * asn_build_sequence - builds an ASN header for a sequence with the ID and
425 * length specified.
426 * On entry, datalength is input as the number of valid bytes following
427 * "data". On exit, it is returned as the number of valid bytes
428 * in this object following the id and length.
430 * This only works on data types < 30, i.e. no extension octets.
431 * The maximum length is 0xFFFF;
433 * Returns a pointer to the first byte of the contents of this object.
434 * Returns 0 on any error.
436 u_char * asn1::build_sequence( u_char *data,
437 int *datalength,
438 u_char type,
439 int length)
441 ACE_TRACE("asn1::build_sequence");
442 *datalength -= 4;
443 if (*datalength < 0){
444 *datalength += 4; /* fix up before punting */
445 return 0;
447 *data++ = type;
448 *data++ = (u_char)(0x02 | ASN_LONG_LEN);
449 *data++ = (u_char)((length >> 8) & 0xFF);
450 *data++ = (u_char)(length & 0xFF);
451 return data;
455 * parse_length - interprets the length of the current object.
456 * On exit, length contains the value of this length field.
458 * Returns a pointer to the first byte after this length
459 * field (aka: the start of the data field).
460 * Returns 0 on any error.
462 u_char * asn1::parse_length( u_char *data,
463 u_long *length)
465 ACE_TRACE("asn1::parse_length");
466 u_char lengthbyte = *data;
468 if (lengthbyte & ASN_LONG_LEN){
469 lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
470 if (lengthbyte == 0){
471 ASNERROR("We don't support indefinite lengths");
472 return 0;
474 if (lengthbyte > sizeof(long)){
475 ASNERROR("we can't support data lengths that long");
476 return 0;
478 // fixed
479 ACE_OS::memcpy((char *)length, (char *)data + 1, (int)lengthbyte);
480 *length = ACE_NTOHL(*length);
481 *length >>= (8 * ((sizeof *length) - lengthbyte));
482 return data + lengthbyte + 1;
483 } else { /* short asnlength */
484 *length = (long)lengthbyte;
485 return data + 1;
489 u_char *asn1::build_length( u_char *data,
490 int *datalength,
491 int length)
493 ACE_TRACE("asn1::build_length");
494 u_char *start_data = data;
496 /* no indefinite lengths sent */
497 if (length < 0x80){
498 if (*datalength < 1){
499 ASNERROR("build_length");
500 return 0;
502 *data++ = (u_char)length;
503 } else if (length <= 0xFF){
504 if (*datalength < 2){
505 ASNERROR("build_length");
506 return 0;
508 *data++ = (u_char)(0x01 | ASN_LONG_LEN);
509 *data++ = (u_char)length;
510 } else { /* 0xFF < length <= 0xFFFF */
511 if (*datalength < 3){
512 ASNERROR("build_length");
513 return 0;
515 *data++ = (u_char)(0x02 | ASN_LONG_LEN);
516 *data++ = (u_char)((length >> 8) & 0xFF);
517 *data++ = (u_char)(length & 0xFF);
519 *datalength -= (data - start_data);
520 return data;
524 * parse_objid - pulls an object indentifier out of an ASN object identifier type.
525 * On entry, datalength is input as the number of valid bytes following
526 * "data". On exit, it is returned as the number of valid bytes
527 * following the beginning of the next object.
529 * "objid" is filled with the object identifier.
531 * Returns a pointer to the first byte past the end
532 * of this object (i.e. the start of the next object).
533 * Returns 0 on any error.
535 u_char *asn1::parse_objid( u_char *data,
536 int *datalength,
537 u_char *type,
538 oid *objid,
539 int *objidlength)
541 ACE_TRACE("asn1::parse_objid");
543 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
544 * subidentifier ::= {leadingbyte}* lastbyte
545 * leadingbyte ::= 1 7bitvalue
546 * lastbyte ::= 0 7bitvalue
548 u_char *bufp = data;
549 oid *oidp = objid + 1;
550 u_long subidentifier;
551 long length;
552 u_long asn_length;
554 *type = *bufp++;
555 bufp = asn1::parse_length(bufp, &asn_length);
556 if (bufp == 0)
557 return 0;
558 if ((int)asn_length + (bufp - data) > *datalength){
559 ASNERROR("overflow of message");
560 return 0;
562 *datalength -= (int)asn_length + (bufp - data);
564 /* Handle invalid object identifier encodings of the form 06 00 robustly */
565 if (asn_length == 0)
566 objid[0] = objid[1] = 0;
568 length = asn_length;
569 (*objidlength)--; /* account for expansion of first byte */
570 while (length > 0 && (*objidlength)-- > 0){
571 subidentifier = 0;
572 do { /* shift and add in low order 7 bits */
573 subidentifier = (subidentifier << 7) + (*(u_char *)bufp & ~ASN_BIT8);
574 length--;
575 } while (*(u_char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */
576 if (subidentifier > (u_long)MAX_SUBID){
577 ASNERROR("subidentifier too long");
578 return 0;
580 *oidp++ = (oid)subidentifier;
584 * The first two subidentifiers are encoded into the first component
585 * with the value (X * 40) + Y, where:
586 * X is the value of the first subidentifier.
587 * Y is the value of the second subidentifier.
589 subidentifier = (u_long)objid[1];
590 if (subidentifier == 0x2B){
591 objid[0] = 1;
592 objid[1] = 3;
593 } else {
594 objid[1] = (u_char)(subidentifier % 40);
595 objid[0] = (u_char)((subidentifier - objid[1]) / 40);
598 *objidlength = (int)(oidp - objid);
599 return bufp;
603 * build_objid - Builds an ASN object identifier object containing the
604 * input string.
605 * On entry, datalength is input as the number of valid bytes following
606 * "data". On exit, it is returned as the number of valid bytes
607 * following the beginning of the next object.
609 * Returns a pointer to the first byte past the end
610 * of this object (i.e. the start of the next object).
611 * Returns 0 on any error.
613 u_char *asn1::build_objid( u_char *data,
614 int *datalength,
615 u_char type,
616 oid *objid,
617 int objidlength)
619 ACE_TRACE("asn1::build_objid");
621 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
622 * subidentifier ::= {leadingbyte}* lastbyte
623 * leadingbyte ::= 1 7bitvalue
624 * lastbyte ::= 0 7bitvalue
626 u_char buf[MAX_OID_LEN];
627 u_char *bp = buf;
628 oid *op = objid;
629 int asnlength;
630 u_long subid, mask, testmask;
631 int bits, testbits;
633 if (objidlength < 2){
634 *bp++ = 0;
635 objidlength = 0;
636 } else {
637 *bp++ = (u_char) (op[1] + (op[0] * 40));
638 objidlength -= 2;
639 op += 2;
642 while(objidlength-- > 0){
643 subid = *op++;
644 if (subid < 127){ /* off by one? */
645 *bp++ = (u_char )subid;
646 } else {
647 mask = 0x7F; /* handle subid == 0 case */
648 bits = 0;
649 /* testmask *MUST* !!!! be of an u_type */
650 for(testmask = 0x7F, testbits = 0; testmask != 0;
651 testmask <<= 7, testbits += 7){
652 if (subid & testmask){ /* if any bits set */
653 mask = testmask;
654 bits = testbits;
657 /* mask can't be zero here */
658 for(;mask != 0x7F; mask >>= 7, bits -= 7){
659 /* fix a mask that got truncated above */
660 if (mask == 0x1E00000)
661 mask = 0xFE00000;
662 *bp++ = (u_char)(((subid & mask) >> bits) | ASN_BIT8);
664 *bp++ = (u_char)(subid & mask);
667 asnlength = bp - buf;
668 data = asn1::build_header(data, datalength, type, asnlength);
669 if (data == 0)
670 return 0;
671 if (*datalength < asnlength)
672 return 0;
673 // fixed
674 ACE_OS::memcpy((char *)data, (char *)buf, asnlength);
675 *datalength -= asnlength;
676 return data + asnlength;
680 * parse_null - Interprets an ASN null type.
681 * On entry, datalength is input as the number of valid bytes following
682 * "data". On exit, it is returned as the number of valid bytes
683 * following the beginning of the next object.
685 * Returns a pointer to the first byte past the end
686 * of this object (i.e. the start of the next object).
687 * Returns 0 on any error.
689 u_char *asn1::parse_null(u_char *data,
690 int *datalength,
691 u_char *type)
693 ACE_TRACE("asn1::parse_null");
695 * ASN.1 null ::= 0x05 0x00
697 u_char *bufp = data;
698 u_long asn_length;
700 *type = *bufp++;
701 bufp = asn1::parse_length(bufp, &asn_length);
702 if (bufp == 0)
703 return 0;
704 if (asn_length != 0){
705 ASNERROR("Malformed 0");
706 return 0;
708 *datalength -= (bufp - data);
709 return bufp + asn_length;
714 * build_null - Builds an ASN null object.
715 * On entry, datalength is input as the number of valid bytes following
716 * "data". On exit, it is returned as the number of valid bytes
717 * following the beginning of the next object.
719 * Returns a pointer to the first byte past the end
720 * of this object (i.e. the start of the next object).
721 * Returns 0 on any error.
723 u_char *asn1::build_null( u_char *data,
724 int *datalength,
725 u_char type)
727 ACE_TRACE("asn1::build_null");
729 * ASN.1 null ::= 0x05 0x00
731 return asn1::build_header(data, datalength, type, 0);
735 * parse_bitstring - pulls a bitstring out of an ASN bitstring type.
736 * On entry, datalength is input as the number of valid bytes following
737 * "data". On exit, it is returned as the number of valid bytes
738 * following the beginning of the next object.
740 * "string" is filled with the bit string.
742 * Returns a pointer to the first byte past the end
743 * of this object (i.e. the start of the next object).
744 * Returns 0 on any error.
746 u_char *asn1::parse_bitstring( u_char *data,
747 int *datalength,
748 u_char *type,
749 u_char *string,
750 int *strlength)
752 ACE_TRACE("asn1::parse_bitstring");
754 * bitstring ::= 0x03 asnlength unused {byte}*
756 u_char *bufp = data;
757 u_long asn_length;
759 *type = *bufp++;
760 bufp = asn1::parse_length(bufp, &asn_length);
761 if (bufp == 0)
762 return 0;
763 if ((int)(asn_length + (bufp - data)) > *datalength){
764 ASNERROR("overflow of message");
765 return 0;
767 if ((int) asn_length > *strlength){
768 ASNERROR("I don't support such long bitstrings");
769 return 0;
771 if (asn_length < 1){
772 ASNERROR("Invalid bitstring");
773 return 0;
775 if (*bufp > 7){
776 ASNERROR("Invalid bitstring");
777 return 0;
779 // fixed
780 ACE_OS::memcpy((char *)string,(char *)bufp, (int)asn_length);
781 *strlength = (int)asn_length;
782 *datalength -= (int)asn_length + (bufp - data);
783 return bufp + asn_length;
788 * build_bitstring - Builds an ASN bit string object containing the
789 * input string.
790 * On entry, datalength is input as the number of valid bytes following
791 * "data". On exit, it is returned as the number of valid bytes
792 * following the beginning of the next object.
794 * Returns a pointer to the first byte past the end
795 * of this object (i.e. the start of the next object).
796 * Returns 0 on any error.
798 u_char *asn1::build_bitstring( u_char *data,
799 int *datalength,
800 u_char type,
801 u_char *string,
802 int strlength)
804 ACE_TRACE("asn1::build_bitstring");
806 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
808 if (strlength < 1 || *string || *string > 7){
809 ASNERROR("Building invalid bitstring");
810 return 0;
812 data = asn1::build_header(data, datalength, type, strlength);
813 if (data == 0)
814 return 0;
815 if (*datalength < strlength)
816 return 0;
817 // fixed
818 ACE_OS::memcpy((char *)data,(char *)string, strlength);
819 *datalength -= strlength;
820 return data + strlength;
825 * parse_unsigned_int64 - pulls a 64 bit u_long out of an ASN int
826 * type.
827 * On entry, datalength is input as the number of valid bytes following
828 * "data". On exit, it is returned as the number of valid bytes
829 * following the end of this object.
831 * Returns a pointer to the first byte past the end
832 * of this object (i.e. the start of the next object).
833 * Returns 0 on any error.
835 u_char * asn1::parse_unsigned_int64(u_char *data,
836 int *datalength,
837 u_char *type,
838 struct counter64 *cp,
839 int countersize)
841 ACE_TRACE("asn1::parse_unsigned_int64");
843 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
845 u_char *bufp = data;
846 u_long asn_length;
847 u_long low = 0, high = 0;
848 int intsize = 4;
850 if (countersize != (int) sizeof(struct counter64)){
851 ASNERROR("not right size");
852 return 0;
854 *type = *bufp++;
855 bufp = asn1::parse_length(bufp, &asn_length);
856 if (bufp == 0){
857 ASNERROR("bad length");
858 return 0;
860 if ((int)(asn_length + (bufp - data)) > *datalength){
861 ASNERROR("overflow of message");
862 return 0;
864 if (((int)asn_length > (intsize * 2 + 1)) ||
865 (((int)asn_length == (intsize * 2) + 1) && *bufp != 0x00)){
866 ASNERROR("I don't support such large integers");
867 return 0;
869 *datalength -= (int)asn_length + (bufp - data);
870 if (*bufp & 0x80){
871 low = (u_long) -1; // integer is negative
872 high = (u_long) -1;
874 while(asn_length--){
875 high = (high << 8) | ((low & 0xFF000000) >> 24);
876 low = (low << 8) | *bufp++;
878 cp->low = low;
879 cp->high = high;
880 return bufp;
885 * build_unsigned_int64 - builds an ASN object containing a 64 bit integer.
886 * On entry, datalength is input as the number of valid bytes following
887 * "data". On exit, it is returned as the number of valid bytes
888 * following the end of this object.
890 * Returns a pointer to the first byte past the end
891 * of this object (i.e. the start of the next object).
892 * Returns 0 on any error.
894 u_char * asn1::build_unsigned_int64( u_char *data,
895 int *datalength,
896 u_char type,
897 struct counter64 *cp,
898 int countersize)
900 ACE_TRACE("asn1::build_unsigned_int64");
902 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
905 u_long low, high;
906 u_long mask, mask2;
907 int add_null_byte = 0;
908 int intsize;
910 if (countersize != (int) sizeof (struct counter64))
911 return 0;
912 intsize = 8;
913 low = cp->low;
914 high = cp->high;
915 mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1));
916 /* mask is 0xFF000000 on a big-endian machine */
917 if ((u_char)((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80){
918 /* if MSB is set */
919 add_null_byte = 1;
920 intsize++;
923 * Truncate "unnecessary" bytes off of the most significant end of this 2's
924 * complement integer.
925 * There should be no sequence of 9 consecutive 1's or 0's at the most
926 * significant end of the integer.
928 mask2 = u_long (0x1FF) << ((8 * (sizeof(u_long) - 1)) - 1);
929 /* mask2 is 0xFF800000 on a big-endian machine */
930 while((((high & mask2) == 0) || ((high & mask2) == mask2))
931 && intsize > 1){
932 intsize--;
933 high = (high << 8)
934 | ((low & mask) >> (8 * (sizeof(long) - 1)));
935 low <<= 8;
937 data = asn1::build_header(data, datalength, type, intsize);
938 if (data == 0)
939 return 0;
940 if (*datalength < intsize)
941 return 0;
942 *datalength -= intsize;
943 if (add_null_byte == 1){
944 *data++ = '\0';
945 intsize--;
947 while(intsize--){
948 *data++ = (u_char)((high & mask) >> (8 * (sizeof(long) - 1)));
949 high = (high << 8)
950 | ((low & mask) >> (8 * (sizeof(long) - 1)));
951 low <<= 8;
953 return data;
957 // create a pdu
958 struct snmp_pdu * cmu_snmp::pdu_create( int command)
960 ACE_TRACE("cmu_snmp::snmp_pdu_create");
961 struct snmp_pdu *pdu;
963 ACE_NEW_RETURN(pdu, snmp_pdu, 0);
964 ACE_OS::memset((char *)pdu, 0,sizeof(struct snmp_pdu));
965 pdu->command = command;
966 pdu->errstat = 0;
967 pdu->errindex = 0;
968 pdu->enterprise = 0;
969 pdu->enterprise_length = 0;
970 pdu->variables = 0;
971 return pdu;
974 // release a pdu from memory
975 void cmu_snmp::free_pdu( struct snmp_pdu *pdu)
977 ACE_TRACE("cmu_snmp::free_pdu");
978 struct variable_list *vp, *ovp;
980 vp = pdu->variables;
981 while(vp){
982 // release the oid part
983 if (vp->name)
984 delete [] vp->name;
985 // if deep data, then release as well
986 if (vp->val.string)
987 delete [] vp->val.string;
988 ovp = vp;
989 // go to the next one
990 vp = vp->next_variable;
991 // release up vb itself
992 delete ovp;
994 // if enterprise release it up
995 if (pdu->enterprise)
996 delete [] pdu->enterprise;
997 // release up pdu itself
998 delete pdu;
1002 // add a null var to a pdu
1003 void cmu_snmp::add_var(struct snmp_pdu *pdu,
1004 oid *name,
1005 int name_length,
1006 SmiVALUE *smival)
1008 ACE_TRACE("cmu_snmp::add_var");
1010 struct variable_list *vars = 0;
1012 // if we don't have a vb list ,create one
1013 if (pdu->variables == 0)
1015 ACE_NEW(pdu->variables, variable_list);
1016 vars = pdu->variables;
1018 else
1019 { // we have one, find the end
1020 for (vars = pdu->variables; vars->next_variable; vars = vars->next_variable)
1022 // Do nothing.
1025 // create one
1026 ACE_NEW(vars->next_variable, variable_list);
1027 // bump ptr
1028 vars = vars->next_variable;
1031 // add the oid with no data
1032 vars->next_variable = 0;
1034 // hook in the Oid portion
1035 ACE_NEW(vars->name, oid[(name_length)]);
1037 // fixed
1038 ACE_OS::memcpy((char *)vars->name,(char *)name, name_length * sizeof(oid));
1039 vars->name_length = name_length;
1041 // hook in the SMI value
1042 switch( smival->syntax)
1044 // null , do nothing
1045 case sNMP_SYNTAX_NULL:
1046 case sNMP_SYNTAX_NOSUCHOBJECT:
1047 case sNMP_SYNTAX_NOSUCHINSTANCE:
1048 case sNMP_SYNTAX_ENDOFMIBVIEW:
1050 vars->type = (u_char) smival->syntax;
1051 vars->val.string = 0;
1052 vars->val_len = 0;
1054 break;
1056 // octects
1057 case sNMP_SYNTAX_OCTETS:
1058 case sNMP_SYNTAX_OPAQUE:
1059 case sNMP_SYNTAX_IPADDR:
1061 vars->type = (u_char) smival->syntax;
1062 ACE_NEW(vars->val.string,
1063 u_char[(unsigned)smival->value.string.len]);
1064 vars->val_len = (int) smival->value.string.len;
1065 ACE_OS::memcpy( (u_char *) vars->val.string,
1066 (u_char *) smival->value.string.ptr,
1067 (unsigned) smival->value.string.len);
1069 break;
1071 // oid
1072 case sNMP_SYNTAX_OID:
1074 vars->type = (u_char) smival->syntax;
1075 vars->val_len = (int) smival->value.oid.len * sizeof(oid);
1076 ACE_NEW(vars->val.objid, oid[(unsigned)vars->val_len]);
1077 ACE_OS::memcpy((u_long *)vars->val.objid,
1078 (u_long *)smival->value.oid.ptr,
1079 (unsigned) vars->val_len);
1081 break;
1084 case sNMP_SYNTAX_TIMETICKS:
1085 case sNMP_SYNTAX_CNTR32:
1086 case sNMP_SYNTAX_GAUGE32:
1087 case sNMP_SYNTAX_UINT32:
1089 long templong;
1090 vars->type = (u_char) smival->syntax;
1091 ACE_NEW(vars->val.integer, long);
1092 vars->val_len = sizeof(long);
1093 templong = (long) smival->value.uNumber;
1094 ACE_OS::memcpy( (long*) vars->val.integer,
1095 (long*) &templong,
1096 sizeof(long));
1098 break;
1100 case sNMP_SYNTAX_INT32:
1102 long templong;
1103 vars->type = (u_char) smival->syntax;
1104 ACE_NEW(vars->val.integer, long);
1105 vars->val_len = sizeof(long);
1106 templong = (long) smival->value.sNumber;
1107 ACE_OS::memcpy( (long*) vars->val.integer,
1108 (long*) &templong,
1109 sizeof(long));
1111 break;
1113 // 64 bit counter
1114 case sNMP_SYNTAX_CNTR64:
1116 vars->type = ( u_char) smival->syntax;
1117 ACE_NEW(vars->val.counter64, counter64);
1118 vars->val_len = sizeof(struct counter64);
1119 ACE_OS::memcpy( (struct counter64*) vars->val.counter64,
1120 (SmiLPCNTR64) &(smival->value.hNumber),
1121 sizeof( SmiCNTR64));
1123 break;
1124 } // end switch
1128 // build the authentication
1129 // works for v1 or v2c
1130 u_char *cmu_snmp::auth_build( u_char *data,
1131 int *length,
1132 long int version,
1133 u_char *community,
1134 int community_len,
1135 int messagelen)
1137 ACE_TRACE("cmu_snmp::auth_build");
1138 u_char *params;
1139 int plen;
1141 params = community;
1142 plen = community_len;
1144 data = asn1::build_sequence(data,
1145 length,
1146 (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
1147 messagelen + plen + 5);
1148 if (data == 0){
1149 ASNERROR("buildheader");
1150 return 0;
1152 data = asn1::build_int(data,
1153 length,
1154 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1155 (long *)&version,
1156 sizeof(version));
1157 if (data == 0){
1158 ASNERROR("buildint");
1159 return 0;
1162 data = asn1::build_string(data,
1163 length,
1164 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
1165 params,
1166 plen );
1167 if (data == 0){
1168 ASNERROR("buildstring");
1169 return 0;
1172 return (u_char *)data;
1176 // build a variable binding
1177 u_char * cmu_snmp::build_var_op(u_char *data, oid * var_name,
1178 int *var_name_len,
1179 u_char var_val_type,
1180 int var_val_len, u_char *var_val,
1181 int *listlength)
1184 ACE_TRACE("cmu_snmp::build_var_op");
1185 int dummyLen, headerLen;
1186 u_char *dataPtr;
1188 dummyLen = *listlength;
1189 dataPtr = data;
1191 data += 4;
1192 dummyLen -=4;
1193 if (dummyLen < 0)
1194 return 0;
1196 headerLen = data - dataPtr;
1197 *listlength -= headerLen;
1198 data = asn1::build_objid( data, listlength,
1199 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
1200 var_name, *var_name_len);
1201 if (data == 0) {
1202 ASNERROR("");
1203 return 0;
1206 // based on the type...
1207 switch(var_val_type) {
1208 case ASN_INTEGER:
1209 data = asn1::build_int( data, listlength, var_val_type, (long *)var_val,
1210 var_val_len);
1211 break;
1213 case SMI_GAUGE:
1214 case SMI_COUNTER:
1215 case SMI_TIMETICKS:
1216 case SMI_UINTEGER:
1217 data = asn1::build_unsigned_int( data,
1218 listlength,
1219 var_val_type,
1220 (u_long *)var_val,
1221 var_val_len);
1222 break;
1224 case SMI_COUNTER64:
1225 data = asn1::build_unsigned_int64(data,
1226 listlength,
1227 var_val_type,
1228 (struct counter64 *)var_val,
1229 var_val_len);
1230 break;
1232 case ASN_OCTET_STR:
1233 case SMI_IPADDRESS:
1234 case SMI_OPAQUE:
1235 case SMI_NSAP:
1236 data = asn1::build_string(data, listlength, var_val_type,
1237 var_val, var_val_len);
1238 break;
1240 case ASN_OBJECT_ID:
1241 data = asn1::build_objid(data, listlength, var_val_type,
1242 (oid *)var_val, var_val_len / sizeof(oid));
1243 break;
1245 case ASN_NULL:
1246 data = asn1::build_null(data, listlength, var_val_type);
1247 break;
1249 case ASN_BIT_STR:
1250 data = asn1::build_bitstring(data, listlength, var_val_type,
1251 var_val, var_val_len);
1252 break;
1254 case SNMP_NOSUCHOBJECT:
1255 case SNMP_NOSUCHINSTANCE:
1256 case SNMP_ENDOFMIBVIEW:
1257 data = asn1::build_null(data, listlength, var_val_type);
1258 break;
1260 default:
1261 ASNERROR("wrong type");
1262 return 0;
1264 if (data == 0) {
1265 ASNERROR("");
1266 return 0;
1268 dummyLen = (data - dataPtr) - headerLen;
1270 asn1::build_sequence(dataPtr, &dummyLen,
1271 (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
1272 dummyLen);
1273 return data;
1277 // serialize the pdu
1278 int cmu_snmp::build( struct snmp_pdu *pdu, u_char *packet,
1279 int *out_length, long version,
1280 u_char* community, int community_len)
1282 ACE_TRACE("cmu_snmp::build");
1283 u_char buf[SNMP_MSG_LENGTH];
1284 u_char *cp;
1285 struct variable_list *vp;
1286 int length;
1287 int totallength;
1289 length = *out_length;
1290 cp = packet;
1291 for(vp = pdu->variables; vp; vp = vp->next_variable) {
1292 cp = cmu_snmp::build_var_op( cp, vp->name,
1293 &vp->name_length, vp->type,
1294 vp->val_len, (u_char *)vp->val.string,
1295 &length);
1296 if (cp == 0)
1297 return -1;
1299 totallength = cp - packet;
1301 length = SNMP_MSG_LENGTH;
1303 // encode the total len
1304 cp = asn1::build_header( buf, &length,
1305 (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
1306 totallength);
1307 if (cp == 0)
1308 return -1;
1309 ACE_OS::memcpy( (char *)cp, (char *)packet,totallength);
1310 totallength += cp - buf;
1312 length = *out_length;
1313 if (pdu->command != TRP_REQ_MSG) {
1314 // request id
1315 cp = asn1::build_int( packet,
1316 &length,
1317 (u_char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1318 (long *)&pdu->reqid,
1319 sizeof(pdu->reqid));
1320 if (cp == 0)
1321 return -1;
1323 // error status
1324 cp = asn1::build_int(cp,
1325 &length,
1326 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1327 (long *)&pdu->errstat, sizeof(pdu->errstat));
1328 if (cp == 0)
1329 return -1;
1331 // error index
1332 cp = asn1::build_int(cp,
1333 &length,
1334 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1335 (long *)&pdu->errindex, sizeof(pdu->errindex));
1336 if (cp == 0)
1337 return -1;
1339 else { // this is a trap message
1341 // enterprise
1342 cp = asn1::build_objid( packet,
1343 &length,
1344 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
1345 (oid *)pdu->enterprise,
1346 pdu->enterprise_length);
1347 if (cp == 0)
1348 return -1;
1350 // agent-addr
1351 cp = asn1::build_string(cp,
1352 &length,
1353 // HDN Fixed to use correct tag
1354 (u_char)SMI_IPADDRESS,
1355 //(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
1356 (u_char *)&pdu->agent_addr.sin_addr.s_addr,
1357 sizeof(pdu->agent_addr.sin_addr.s_addr));
1358 if (cp == 0)
1359 return -1;
1361 long tmp (static_cast <long> (pdu->trap_type));
1362 // generic trap
1363 cp = asn1::build_int(cp,
1364 &length,
1365 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1366 &tmp,
1367 sizeof(pdu->trap_type));
1368 if (cp == 0)
1369 return -1;
1371 tmp = static_cast <long> (pdu->specific_type);
1372 // specific trap
1373 cp = asn1::build_int( cp,
1374 &length,
1375 (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1376 &tmp,
1377 sizeof(pdu->specific_type));
1378 if (cp == 0)
1379 return -1;
1381 // timestamp
1382 cp = asn1::build_int(cp,
1383 &length,
1384 // HDN Fixed to use correct tag
1385 (u_char)SMI_TIMETICKS,
1386 //(u_char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1387 (long *)&pdu->time,
1388 sizeof(pdu->time));
1389 if (cp == 0)
1390 return -1;
1393 if (length < totallength)
1394 return -1;
1395 // fixed
1396 ACE_OS::memcpy((char *)cp, (char *)buf, totallength);
1397 totallength += cp - packet;
1399 length = SNMP_MSG_LENGTH;
1400 cp = asn1::build_header(buf,
1401 &length,
1402 (u_char)pdu->command,
1403 totallength);
1404 if (cp == 0)
1405 return -1;
1406 if (length < totallength)
1407 return -1;
1408 // fixed
1409 ACE_OS::memcpy((char *)cp, (char *)packet, totallength);
1410 totallength += cp - buf;
1412 length = *out_length;
1414 cp = cmu_snmp::auth_build( packet,
1415 &length,
1416 version,
1417 community,
1418 community_len,
1419 totallength );
1420 if (cp == 0)
1421 return -1;
1422 if ((*out_length - (cp - packet)) < totallength)
1423 return -1;
1424 // fixed
1425 ACE_OS::memcpy((char *)cp, (char *)buf, totallength);
1426 totallength += cp - packet;
1427 *out_length = totallength;
1429 return 0;
1432 // parse the authentication header
1433 u_char *cmu_snmp::auth_parse(u_char *data,
1434 int *length, u_char *sid,
1435 int *slen, long *version)
1437 ACE_TRACE("cmu_snmp::auth_parse");
1438 u_char type;
1440 // get the type
1441 data = asn1::parse_header( data, length, &type);
1442 if (data == 0){
1443 ASNERROR("bad header");
1444 return 0;
1447 if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
1448 ASNERROR("wrong auth header type");
1449 return 0;
1452 // get the version
1453 data = asn1::parse_int(data, length, &type, version, sizeof(*version));
1454 if (data == 0) {
1455 ASNERROR("bad parse of version");
1456 return 0;
1459 // get the community name
1460 data = asn1::parse_string(data, length, &type, sid, slen);
1461 if (data == 0) {
1462 ASNERROR("bad parse of community");
1463 return 0;
1466 return (u_char *)data;
1469 /* u_char *data, // IN - pointer to the start of object
1470 oid *var_name, // OUT - object id of variable
1471 int *var_name_len, // IN/OUT - length of variable name
1472 u_char *var_val_type, // OUT - type of variable
1473 (int or octet string) (one byte)
1474 int *var_val_len, // OUT - length of variable
1475 u_char **var_val, // OUT - pointer to ASN1 encoded value of variable
1478 u_char *
1479 cmu_snmp::parse_var_op( u_char *data, oid *var_name,
1480 int *var_name_len, u_char *var_val_type,
1481 int *var_val_len, u_char **var_val,
1482 int *listlength)
1484 ACE_TRACE("cmu_snmp::parse_var_op");
1485 u_char var_op_type;
1486 int var_op_len = *listlength;
1487 u_char *var_op_start = data;
1489 data = asn1::parse_header(data, &var_op_len, &var_op_type);
1490 if (data == 0){
1491 ASNERROR("");
1492 return 0;
1494 if (var_op_type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR))
1495 return 0;
1496 data = asn1::parse_objid(data, &var_op_len, &var_op_type, var_name, var_name_len);
1497 if (data == 0) {
1498 ASNERROR("");
1499 return 0;
1501 if (var_op_type != (u_char)
1502 (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID))
1503 return 0;
1504 *var_val = data; /* save pointer to this object */
1505 /* find out what type of object this is */
1506 data = asn1::parse_header(data, &var_op_len, var_val_type);
1507 if (data == 0) {
1508 ASNERROR("");
1509 return 0;
1511 *var_val_len = var_op_len;
1512 data += var_op_len;
1513 *listlength -= (int)(data - var_op_start);
1514 return data;
1518 // build a pdu from a data and length
1519 int cmu_snmp::parse( struct snmp_pdu *pdu,
1520 u_char *data,
1521 u_char *community_name,
1522 u_long &community_len,
1523 snmp_version &spp_version,
1524 int length)
1526 ACE_TRACE("cmu_snmp::parse");
1527 u_char msg_type;
1528 u_char type;
1529 u_char *var_val;
1530 long version;
1531 int len, four;
1532 u_char community[256];
1533 int community_length = 256;
1534 struct variable_list *vp = 0;
1535 oid objid[MAX_NAME_LEN], *op;
1537 // authenticates message and returns length if valid
1538 data = cmu_snmp::auth_parse(data,
1539 &length,
1540 community,
1541 &community_length,
1542 &version);
1543 if (data == 0)
1544 return -1;
1546 // copy the returned community name
1547 ACE_OS::memcpy( (u_char *) community_name,
1548 (u_char *) community,
1549 community_length);
1550 community_len = (long) community_length;
1552 if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C ) {
1553 ASNERROR("Wrong version");
1554 return -1;
1557 spp_version = (snmp_version) version;
1559 data = asn1::parse_header(data,
1560 &length,
1561 &msg_type);
1562 if (data == 0)
1563 return -1;
1564 pdu->command = msg_type;
1566 if (pdu->command != TRP_REQ_MSG){
1567 // get the rid
1568 data = asn1::parse_int(data,
1569 &length, &type,
1570 (long *)&pdu->reqid,
1571 sizeof(pdu->reqid));
1572 if (data == 0)
1573 return -1;
1574 // get the error status
1575 data = asn1::parse_int(data,
1576 &length,
1577 &type,
1578 (long *)&pdu->errstat,
1579 sizeof(pdu->errstat));
1580 if (data == 0)
1581 return -1;
1582 // get the error index
1583 data = asn1::parse_int(data,
1584 &length,
1585 &type,
1586 (long *)&pdu->errindex,
1587 sizeof(pdu->errindex));
1588 if (data == 0)
1589 return -1;
1591 else { // is a trap
1593 // get the enterprise
1594 pdu->enterprise_length = MAX_NAME_LEN;
1595 data = asn1::parse_objid(data,
1596 &length,
1597 &type,
1598 objid,
1599 &pdu->enterprise_length);
1600 if (data == 0)
1601 return -1;
1603 ACE_NEW_RETURN(pdu->enterprise,
1604 oid[pdu->enterprise_length*sizeof(oid)],-1);
1606 // fixed
1607 ACE_OS::memcpy((char *)pdu->enterprise,(char *)objid,
1608 pdu->enterprise_length * sizeof(oid));
1610 // get source address
1611 four = 4;
1612 data = asn1::parse_string(data, &length, &type,
1613 (u_char *)&pdu->agent_addr.sin_addr.s_addr,
1614 &four);
1615 if (data == 0)
1616 return -1;
1618 long tmp (static_cast <long> (pdu->trap_type));
1620 // get trap type
1621 data = asn1::parse_int(data, &length, &type, &tmp,
1622 sizeof(pdu->trap_type));
1623 if (data == 0)
1624 return -1;
1626 // trap type
1627 tmp = static_cast <long> (pdu->specific_type);
1628 data = asn1::parse_int(data, &length, &type, &tmp,
1629 sizeof(pdu->specific_type));
1630 if (data == 0)
1631 return -1;
1633 // timestamp
1634 data = asn1::parse_int(data, &length, &type, (long *)&pdu->time,
1635 sizeof(pdu->time));
1636 if (data == 0)
1637 return -1;
1640 // get the vb list
1641 data = asn1::parse_header(data, &length, &type);
1642 if (data == 0)
1643 return -1;
1645 if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR))
1646 return -1;
1648 while((int)length > 0) {
1649 if (pdu->variables == 0) {
1650 ACE_NEW_RETURN(pdu->variables, variable_list, -1);
1651 vp = pdu->variables;
1652 } else {
1653 ACE_NEW_RETURN(vp->next_variable, variable_list, -1);
1654 vp = vp->next_variable;
1656 vp->next_variable = 0;
1657 vp->val.string = 0;
1658 vp->name = 0;
1659 vp->name_length = MAX_NAME_LEN;
1660 data = cmu_snmp::parse_var_op( data, objid,
1661 &vp->name_length, &vp->type,
1662 &vp->val_len, &var_val,
1663 (int *)&length);
1664 if (data == 0)
1665 return -1;
1667 ACE_NEW_RETURN(op, oid[(unsigned)vp->name_length * sizeof(oid)], -1);
1669 // fixed
1670 ACE_OS::memcpy((char *)op, (char *)objid, vp->name_length * sizeof(oid));
1671 vp->name = op;
1673 len = SNMP_MSG_LENGTH;
1674 switch((short)vp->type) {
1675 case ASN_INTEGER:
1676 case SMI_COUNTER:
1677 case SMI_GAUGE:
1678 case SMI_TIMETICKS:
1679 case SMI_UINTEGER:
1680 ACE_NEW_RETURN(vp->val.integer,long, -1);
1681 vp->val_len = sizeof(long);
1682 asn1::parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer));
1683 break;
1684 case SMI_COUNTER64:
1685 ACE_NEW_RETURN(vp->val.counter64, counter64, -1);
1686 vp->val_len = sizeof(struct counter64);
1687 asn1::parse_unsigned_int64(var_val, &len, &vp->type,
1688 (struct counter64 *)vp->val.counter64,
1689 sizeof(*vp->val.counter64));
1690 break;
1692 case ASN_OCTET_STR:
1693 case SMI_IPADDRESS:
1694 case SMI_OPAQUE:
1695 case SMI_NSAP:
1696 ACE_NEW_RETURN(vp->val.string, u_char[(unsigned)vp->val_len + 1], -1);
1697 asn1::parse_string(var_val, &len, &vp->type, vp->val.string,
1698 &vp->val_len);
1699 break;
1701 case ASN_OBJECT_ID:
1702 vp->val_len = MAX_NAME_LEN;
1703 asn1::parse_objid(var_val, &len, &vp->type, objid, &vp->val_len);
1704 //vp->val_len *= sizeof(oid);
1706 ACE_NEW_RETURN(vp->val.objid, oid[(unsigned)vp->val_len*sizeof(oid)], -1);
1708 // fixed
1709 ACE_OS::memcpy((char *)vp->val.objid,
1710 (char *)objid,
1711 vp->val_len * sizeof(oid));
1712 break;
1714 case SNMP_NOSUCHOBJECT:
1715 case SNMP_NOSUCHINSTANCE:
1716 case SNMP_ENDOFMIBVIEW:
1717 case ASN_NULL:
1718 break;
1719 default:
1720 ASNERROR("bad type returned ");
1721 break;
1724 return 0;