]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/snmplib/asn1.c
2 * Abstract Syntax Notation One, ASN.1
3 * As defined in ISO/IS 8824 and ISO/IS 8825
4 * This implements a subset of the above International Standards that
5 * is sufficient to implement SNMP.
7 * Encodes abstract data types into a machine independent stream of bytes.
10 /***************************************************************************
12 * Copyright 1997 by Carnegie Mellon University
16 * Permission to use, copy, modify, and distribute this software and its
17 * documentation for any purpose and without fee is hereby granted,
18 * provided that the above copyright notice appear in all copies and that
19 * both that copyright notice and this permission notice appear in
20 * supporting documentation, and that the name of CMU not be
21 * used in advertising or publicity pertaining to distribution of the
22 * software without specific, written prior permission.
24 * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
25 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
26 * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
27 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
28 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
29 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
32 ***************************************************************************/
45 #include <sys/types.h>
51 #include <gnumalloc.h>
68 #include <sys/socket.h>
71 #include <netinet/in.h>
74 #include <arpa/inet.h>
84 #include "snmp_api_error.h"
87 asn_build_header(u_char
* data
, /* IN - ptr to start of object */
88 int *datalength
, /* IN/OUT - # of valid bytes */
90 u_char type
, /* IN - ASN type of object */
92 { /* IN - length of object */
93 /* Truth is 0 'cause we don't know yet */
94 return (asn_build_header_with_truth(data
, datalength
, type
, length
, 0));
98 * asn_parse_int - pulls an int out of an ASN int type.
99 * On entry, datalength is input as the number of valid bytes following
100 * "data". On exit, it is returned as the number of valid bytes
101 * following the end of this object.
103 * Returns a pointer to the first byte past the end
104 * of this object (i.e. the start of the next object).
105 * Returns NULL on any error.
108 asn_parse_int(u_char
* data
, int *datalength
,
109 u_char
* type
, int *intp
, int intsize
)
110 /* u_char *data; IN - pointer to start of object */
111 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
112 /* u_char *type; OUT - asn type of object */
113 /* int *intp; IN/OUT - pointer to start of output buffer */
114 /* int intsize; IN - size of output buffer */
117 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
123 /* Room to store int? */
124 if (intsize
!= sizeof(int)) {
125 snmp_set_api_error(SNMPERR_ASN_DECODE
);
132 bufp
= asn_parse_length(bufp
, &asn_length
);
136 /* Make sure the entire int is in the buffer */
137 if (asn_length
+ (bufp
- data
) > *datalength
) {
138 snmp_set_api_error(SNMPERR_ASN_DECODE
);
141 /* Can we store this int? */
142 if (asn_length
> intsize
) {
143 snmp_set_api_error(SNMPERR_ASN_DECODE
);
147 *datalength
-= (int) asn_length
+ (bufp
- data
);
149 /* Is the int negative? */
151 value
= -1; /* integer is negative */
153 /* Extract the bytes */
155 value
= (value
<< 8) | *bufp
++;
163 * asn_parse_unsigned_int - pulls an unsigned int out of an ASN int type.
164 * On entry, datalength is input as the number of valid bytes following
165 * "data". On exit, it is returned as the number of valid bytes
166 * following the end of this object.
168 * Returns a pointer to the first byte past the end
169 * of this object (i.e. the start of the next object).
170 * Returns NULL on any error.
173 asn_parse_unsigned_int(u_char
* data
, int *datalength
,
174 u_char
* type
, u_int
* intp
, int intsize
)
175 /* u_char *data; IN - pointer to start of object */
176 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
177 /* u_char *type; OUT - asn type of object */
178 /* u_int *intp; IN/OUT - pointer to start of output buffer */
179 /* int intsize; IN - size of output buffer */
182 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
188 /* Room to store int? */
189 if (intsize
!= sizeof(int)) {
190 snmp_set_api_error(SNMPERR_ASN_DECODE
);
197 bufp
= asn_parse_length(bufp
, &asn_length
);
201 /* Make sure the entire int is in the buffer */
202 if (asn_length
+ (bufp
- data
) > *datalength
) {
203 snmp_set_api_error(SNMPERR_ASN_DECODE
);
206 /* Can we store this int? */
207 if ((asn_length
> (intsize
+ 1)) ||
208 ((asn_length
== intsize
+ 1) && *bufp
!= 0x00)) {
209 snmp_set_api_error(SNMPERR_ASN_DECODE
);
213 *datalength
-= (int) asn_length
+ (bufp
- data
);
215 /* Is the int negative? */
217 value
= -1; /* integer is negative */
219 /* Extract the bytes */
221 value
= (value
<< 8) | *bufp
++;
229 * asn_build_int - builds an ASN object containing an integer.
230 * On entry, datalength is input as the number of valid bytes following
231 * "data". On exit, it is returned as the number of valid bytes
232 * following the end of this object.
234 * Returns a pointer to the first byte past the end
235 * of this object (i.e. the start of the next object).
236 * Returns NULL on any error.
239 asn_build_int(u_char
* data
, int *datalength
,
240 u_char type
, int *intp
, int intsize
)
241 /* u_char *data; IN - pointer to start of output buffer */
242 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
243 /* u_char type; IN - asn type of object */
244 /* int *intp; IN - pointer to start of integer */
245 /* int intsize; IN - size of *intp */
248 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
253 if (intsize
!= sizeof(int)) {
254 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
260 * Truncate "unnecessary" bytes off of the most significant end of this
261 * 2's complement integer. There should be no sequence of 9
262 * consecutive 1's or 0's at the most significant end of the
265 mask
= (u_int
) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
266 /* mask is 0xFF800000 on a big-endian machine */
268 while ((((integer
& mask
) == 0) || ((integer
& mask
) == mask
))
274 data
= asn_build_header_with_truth(data
, datalength
, type
, intsize
, 1);
278 /* Enough room for what we just encoded? */
279 if (*datalength
< intsize
) {
280 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
284 *datalength
-= intsize
;
285 mask
= (u_int
) 0xFF << (8 * (sizeof(int) - 1));
286 /* mask is 0xFF000000 on a big-endian machine */
288 *data
++ = (u_char
) ((integer
& mask
) >> (8 * (sizeof(int) - 1)));
295 * asn_build_unsigned_int - builds an ASN object containing an integer.
296 * On entry, datalength is input as the number of valid bytes following
297 * "data". On exit, it is returned as the number of valid bytes
298 * following the end of this object.
300 * Returns a pointer to the first byte past the end
301 * of this object (i.e. the start of the next object).
302 * Returns NULL on any error.
305 asn_build_unsigned_int(u_char
* data
, int *datalength
,
306 u_char type
, u_int
* intp
, int intsize
)
307 /* u_char *data; IN - pointer to start of output buffer */
308 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
309 /* u_char type; IN - asn type of object */
310 /* u_int *intp; IN - pointer to start of integer */
311 /* int intsize; IN - size of *intp */
314 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
318 int add_null_byte
= 0;
320 if (intsize
!= sizeof(int)) {
321 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
325 mask
= (u_int
) 0x80 << (8 * (sizeof(int) - 1));
326 /* mask is 0x80000000 on a big-endian machine */
327 if ((integer
& mask
) != 0) {
328 /* add a null byte if MSB is set, to prevent sign extension */
333 * Truncate "unnecessary" bytes off of the most significant end of
334 * this 2's complement integer.
335 * There should be no sequence of 9 consecutive 1's or 0's at the
336 * most significant end of the integer.
337 * The 1's case is taken care of above by adding a null byte.
339 mask
= (u_int
) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
340 /* mask is 0xFF800000 on a big-endian machine */
341 while (((integer
& mask
) == 0) && intsize
> 1) {
346 data
= asn_build_header_with_truth(data
, datalength
, type
, intsize
, 1);
350 if (*datalength
< intsize
) {
351 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
354 *datalength
-= intsize
;
355 if (add_null_byte
== 1) {
359 mask
= (u_int
) 0xFF << (8 * (sizeof(int) - 1));
360 /* mask is 0xFF000000 on a big-endian machine */
362 *data
++ = (u_char
) ((integer
& mask
) >> (8 * (sizeof(int) - 1)));
369 * asn_parse_string - pulls an octet string out of an ASN octet string type.
370 * On entry, datalength is input as the number of valid bytes following
371 * "data". On exit, it is returned as the number of valid bytes
372 * following the beginning of the next object.
374 * "string" is filled with the octet string.
376 * Returns a pointer to the first byte past the end
377 * of this object (i.e. the start of the next object).
378 * Returns NULL on any error.
381 asn_parse_string(u_char
* data
, int *datalength
,
382 u_char
* type
, u_char
* string
, int *strlength
)
383 /* u_char *data; IN - pointer to start of object */
384 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
385 /* u_char *type; OUT - asn type of object */
386 /* u_char *string; IN/OUT - pointer to start of output buffer */
387 /* int *strlength; IN/OUT - size of output buffer */
390 * ASN.1 octet string ::= primstring | cmpdstring
391 * primstring ::= 0x04 asnlength byte {byte}*
392 * cmpdstring ::= 0x24 asnlength string {string}*
398 bufp
= asn_parse_length(bufp
, &asn_length
);
402 if (asn_length
+ (bufp
- data
) > *datalength
) {
403 snmp_set_api_error(SNMPERR_ASN_DECODE
);
406 if (asn_length
> *strlength
) {
407 snmp_set_api_error(SNMPERR_ASN_DECODE
);
410 memcpy((char *) string
, (char *) bufp
, (int) asn_length
);
411 *strlength
= (int) asn_length
;
412 *datalength
-= (int) asn_length
+ (bufp
- data
);
413 return (bufp
+ asn_length
);
417 * asn_build_string - Builds an ASN octet string object containing the input
418 * string. On entry, datalength is input as the number of valid bytes
419 * following "data". On exit, it is returned as the number of valid bytes
420 * following the beginning of the next object.
422 * Returns a pointer to the first byte past the end
423 * of this object (i.e. the start of the next object).
424 * Returns NULL on any error.
427 asn_build_string(u_char
* data
, int *datalength
,
428 u_char type
, u_char
* string
, int strlength
)
429 /* u_char *data; IN - pointer to start of object */
430 /* int *datalength; IN/OUT - # of valid bytes left in buf */
431 /* u_char type; IN - ASN type of string */
432 /* u_char *string; IN - pointer to start of input buffer */
433 /* int strlength; IN - size of input buffer */
436 * ASN.1 octet string ::= primstring | cmpdstring
437 * primstring ::= 0x04 asnlength byte {byte}*
438 * cmpdstring ::= 0x24 asnlength string {string}*
439 * This code will never send a compound string.
441 data
= asn_build_header_with_truth(data
, datalength
, type
, strlength
, 1);
445 if (*datalength
< strlength
) {
446 snmp_set_api_error(SNMPERR_ASN_DECODE
);
449 memcpy((char *) data
, (char *) string
, strlength
);
450 *datalength
-= strlength
;
451 return (data
+ strlength
);
455 * asn_parse_header - interprets the ID and length of the current object.
456 * On entry, datalength is input as the number of valid bytes following
457 * "data". On exit, it is returned as the number of valid bytes
458 * in this object following the id and length.
460 * Returns a pointer to the first byte of the contents of this object.
461 * Returns NULL on any error.
464 asn_parse_header(u_char
* data
, int *datalength
, u_char
* type
)
465 /* u_char *data; IN - pointer to start of object */
466 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
467 /* u_char *type; OUT - ASN type of object */
473 /* this only works on data types < 30, i.e. no extension octets */
474 if (IS_EXTENSION_ID(*bufp
)) {
475 snmp_set_api_error(SNMPERR_ASN_DECODE
);
479 bufp
= asn_parse_length(bufp
+ 1, &asn_length
);
483 header_len
= bufp
- data
;
484 if (header_len
+ asn_length
> *datalength
|| asn_length
> (u_int
)(2 << 18) ) {
485 snmp_set_api_error(SNMPERR_ASN_DECODE
);
488 *datalength
= (int) asn_length
;
493 * asn_build_header - builds an ASN header for an object with the ID and
495 * On entry, datalength is input as the number of valid bytes following
496 * "data". On exit, it is returned as the number of valid bytes
497 * in this object following the id and length.
499 * This only works on data types < 30, i.e. no extension octets.
500 * The maximum length is 0xFFFF;
502 * Returns a pointer to the first byte of the contents of this object.
503 * Returns NULL on any error.
507 asn_build_header_with_truth(u_char
* data
, int *datalength
,
508 u_char type
, int length
, int truth
)
509 /* u_char *data; IN - pointer to start of object */
510 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
511 /* u_char type; IN - ASN type of object */
512 /* int length; IN - length of object */
513 /* int truth; IN - Whether length is truth */
515 if (*datalength
< 1) {
516 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
521 return (asn_build_length(data
, datalength
, length
, truth
));
526 * asn_build_sequence - builds an ASN header for a sequence with the ID and
528 * On entry, datalength is input as the number of valid bytes following
529 * "data". On exit, it is returned as the number of valid bytes
530 * in this object following the id and length.
532 * This only works on data types < 30, i.e. no extension octets.
533 * The maximum length is 0xFFFF;
535 * Returns a pointer to the first byte of the contents of this object.
536 * Returns NULL on any error.
539 asn_build_sequence(u_char
* data
, int *datalength
,
540 u_char type
, int length
)
541 /* u_char *data; IN - pointer to start of object */
542 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
543 /* u_char type; IN - ASN type of object */
544 /* int length; IN - length of object */
547 if (*datalength
< 0) {
548 *datalength
+= 4; /* fix up before punting */
549 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
553 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
554 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
555 *data
++ = (u_char
) (length
& 0xFF);
561 * asn_parse_length - interprets the length of the current object.
562 * On exit, length contains the value of this length field.
564 * Returns a pointer to the first byte after this length
565 * field (aka: the start of the data field).
566 * Returns NULL on any error.
569 asn_parse_length(u_char
* data
, u_int
* length
)
570 /* u_char *data; IN - pointer to start of length field */
571 /* u_int *length; OUT - value of length field */
573 u_char lengthbyte
= *data
;
575 if (lengthbyte
& ASN_LONG_LEN
) {
576 lengthbyte
&= ~ASN_LONG_LEN
; /* turn MSb off */
578 if (lengthbyte
== 0) {
579 snmp_set_api_error(SNMPERR_ASN_DECODE
);
582 if (lengthbyte
> sizeof(int)) {
583 snmp_set_api_error(SNMPERR_ASN_DECODE
);
587 memcpy((char *) (length
), (char *) data
+ 1, (int) lengthbyte
);
588 *length
= ntohl(*length
);
589 *length
>>= (8 * ((sizeof *length
) - lengthbyte
));
590 return (data
+ lengthbyte
+ 1);
593 /* short asnlength */
595 *length
= (int) lengthbyte
;
600 asn_build_length(u_char
* data
, int *datalength
,
601 int length
, int truth
)
602 /* u_char *data; IN - pointer to start of object */
603 /* int *datalength; IN/OUT - # of valid bytes left in buf */
604 /* int length; IN - length of object */
605 /* int truth; IN - If 1, this is the true len. */
607 u_char
*start_data
= data
;
611 /* no indefinite lengths sent */
613 if (*datalength
< 1) {
614 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
617 *data
++ = (u_char
) length
;
619 } else if (length
<= 0xFF) {
620 if (*datalength
< 2) {
621 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
624 *data
++ = (u_char
) (0x01 | ASN_LONG_LEN
);
625 *data
++ = (u_char
) length
;
626 } else { /* 0xFF < length <= 0xFFFF */
627 if (*datalength
< 3) {
628 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
631 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
632 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
633 *data
++ = (u_char
) (length
& 0xFF);
638 /* Don't know if this is the true length. Make sure it's large
641 if (*datalength
< 3) {
642 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
645 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
646 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
647 *data
++ = (u_char
) (length
& 0xFF);
650 *datalength
-= (data
- start_data
);
655 * asn_parse_objid - pulls an object indentifier out of an ASN object
657 * On entry, datalength is input as the number of valid bytes following
658 * "data". On exit, it is returned as the number of valid bytes
659 * following the beginning of the next object.
661 * "objid" is filled with the object identifier.
663 * Returns a pointer to the first byte past the end
664 * of this object (i.e. the start of the next object).
665 * Returns NULL on any error.
668 asn_parse_objid(u_char
* data
, int *datalength
,
669 u_char
* type
, oid
* objid
, int *objidlength
)
670 /* u_char *data; IN - pointer to start of object */
671 /* int *datalength; IN/OUT - # of valid bytes left in buf */
672 /* u_char *type; OUT - ASN type of object */
673 /* oid *objid; IN/OUT - pointer to start of output buffer */
674 /* int *objidlength; IN/OUT - number of sub-id's in objid */
677 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
678 * subidentifier ::= {leadingbyte}* lastbyte
679 * leadingbyte ::= 1 7bitvalue
680 * lastbyte ::= 0 7bitvalue
683 oid
*oidp
= objid
+ 1;
689 bufp
= asn_parse_length(bufp
, &asn_length
);
693 if (asn_length
+ (bufp
- data
) > *datalength
) {
694 snmp_set_api_error(SNMPERR_ASN_DECODE
);
697 *datalength
-= (int) asn_length
+ (bufp
- data
);
699 /* Handle invalid object identifier encodings of the form 06 00 robustly */
701 objid
[0] = objid
[1] = 0;
704 (*objidlength
)--; /* account for expansion of first byte */
705 while (length
> 0 && (*objidlength
)-- > 0) {
708 do { /* shift and add in low order 7 bits */
709 subidentifier
= (subidentifier
<< 7)
710 + (*(u_char
*) bufp
& ~ASN_BIT8
);
712 } while (*(u_char
*) bufp
++ & ASN_BIT8
);
714 /* while last byte has high bit clear */
715 if (subidentifier
> (u_int
) MAX_SUBID
) {
716 snmp_set_api_error(SNMPERR_ASN_DECODE
);
719 *oidp
++ = (oid
) subidentifier
;
723 * The first two subidentifiers are encoded into the first component
724 * with the value (X * 40) + Y, where:
725 * X is the value of the first subidentifier.
726 * Y is the value of the second subidentifier.
728 subidentifier
= (u_int
) objid
[1];
729 if (subidentifier
== 0x2B) {
733 objid
[1] = (u_char
) (subidentifier
% 40);
734 objid
[0] = (u_char
) ((subidentifier
- objid
[1]) / 40);
737 *objidlength
= (int) (oidp
- objid
);
742 * asn_build_objid - Builds an ASN object identifier object containing the
744 * On entry, datalength is input as the number of valid bytes following
745 * "data". On exit, it is returned as the number of valid bytes
746 * following the beginning of the next object.
748 * Returns a pointer to the first byte past the end
749 * of this object (i.e. the start of the next object).
750 * Returns NULL on any error.
753 asn_build_objid(u_char
* data
, int *datalength
,
754 u_char type
, oid
* objid
, int objidlength
)
755 /* u_char *data; IN - pointer to start of object */
756 /* int *datalength; IN/OUT - # of valid bytes left in buf */
757 /* u_char type; IN - ASN type of object */
758 /* oid *objid; IN - pointer to start of input buffer */
759 /* int objidlength; IN - number of sub-id's in objid */
762 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
763 * subidentifier ::= {leadingbyte}* lastbyte
764 * leadingbyte ::= 1 7bitvalue
765 * lastbyte ::= 0 7bitvalue
767 u_char buf
[MAX_OID_LEN
];
771 u_int subid
, mask
, testmask
;
774 if (objidlength
< 2) {
778 *bp
++ = op
[1] + (op
[0] * 40);
783 while (objidlength
-- > 0) {
785 if (subid
< 127) { /* off by one? */
788 mask
= 0x7F; /* handle subid == 0 case */
790 /* testmask *MUST* !!!! be of an unsigned type */
791 for (testmask
= 0x7F, testbits
= 0; testmask
!= 0;
792 testmask
<<= 7, testbits
+= 7) {
793 if (subid
& testmask
) { /* if any bits set */
798 /* mask can't be zero here */
799 for (; mask
!= 0x7F; mask
>>= 7, bits
-= 7) {
800 /* fix a mask that got truncated above */
801 if (mask
== 0x1E00000)
803 *bp
++ = (u_char
) (((subid
& mask
) >> bits
) | ASN_BIT8
);
805 *bp
++ = (u_char
) (subid
& mask
);
809 asnlength
= bp
- buf
;
810 data
= asn_build_header_with_truth(data
, datalength
, type
, asnlength
, 1);
813 if (*datalength
< asnlength
) {
814 snmp_set_api_error(SNMPERR_ASN_DECODE
);
817 memcpy((char *) data
, (char *) buf
, asnlength
);
818 *datalength
-= asnlength
;
819 return (data
+ asnlength
);
824 * asn_parse_null - Interprets an ASN null type.
825 * On entry, datalength is input as the number of valid bytes following
826 * "data". On exit, it is returned as the number of valid bytes
827 * following the beginning of the next object.
829 * Returns a pointer to the first byte past the end
830 * of this object (i.e. the start of the next object).
831 * Returns NULL on any error.
834 asn_parse_null(u_char
* data
, int *datalength
, u_char
* type
)
835 /* u_char *data; IN - pointer to start of object */
836 /* int *datalength; IN/OUT - # of valid bytes left in buf */
837 /* u_char *type; OUT - ASN type of object */
840 * ASN.1 null ::= 0x05 0x00
846 bufp
= asn_parse_length(bufp
, &asn_length
);
850 if (asn_length
!= 0) {
851 snmp_set_api_error(SNMPERR_ASN_DECODE
);
854 *datalength
-= (bufp
- data
);
855 return (bufp
+ asn_length
);
860 * asn_build_null - Builds an ASN null object.
861 * On entry, datalength is input as the number of valid bytes following
862 * "data". On exit, it is returned as the number of valid bytes
863 * following the beginning of the next object.
865 * Returns a pointer to the first byte past the end
866 * of this object (i.e. the start of the next object).
867 * Returns NULL on any error.
870 asn_build_null(u_char
* data
, int *datalength
, u_char type
)
871 /* u_char *data; IN - pointer to start of object */
872 /* int *datalength; IN/OUT - # of valid bytes left in buf */
873 /* u_char type; IN - ASN type of object */
876 * ASN.1 null ::= 0x05 0x00
878 return (asn_build_header_with_truth(data
, datalength
, type
, 0, 1));
884 * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type.
885 * On entry, datalength is input as the number of valid bytes following
886 * "data". On exit, it is returned as the number of valid bytes
887 * following the beginning of the next object.
889 * "string" is filled with the bit string.
891 * Returns a pointer to the first byte past the end
892 * of this object (i.e. the start of the next object).
893 * Returns NULL on any error.
896 asn_parse_bitstring(u_char
* data
, int *datalength
,
897 u_char
* type
, u_char
* string
, int *strlength
)
898 /* u_char *data; IN - pointer to start of object */
899 /* int *datalength; IN/OUT - # of valid bytes left in buf */
900 /* u_char *type; OUT - asn type of object */
901 /* u_char *string; IN/OUT - pointer to start of output buf */
902 /* int *strlength; IN/OUT - size of output buffer */
905 * bitstring ::= 0x03 asnlength unused {byte}*
911 bufp
= asn_parse_length(bufp
, &asn_length
);
915 if (asn_length
+ (bufp
- data
) > *datalength
) {
916 snmp_set_api_error(SNMPERR_ASN_DECODE
);
919 if (asn_length
> *strlength
) {
920 snmp_set_api_error(SNMPERR_ASN_DECODE
);
923 if (asn_length
< 1) {
924 snmp_set_api_error(SNMPERR_ASN_DECODE
);
927 if ((int) (*(char *) bufp
) < 0 || (int) (*bufp
) > 7) {
928 snmp_set_api_error(SNMPERR_ASN_DECODE
);
931 memcpy((char *) string
, (char *) bufp
, (int) asn_length
);
932 *strlength
= (int) asn_length
;
933 *datalength
-= (int) asn_length
+ (bufp
- data
);
934 return (bufp
+ asn_length
);
938 * asn_build_bitstring - Builds an ASN bit string object containing the
940 * On entry, datalength is input as the number of valid bytes following
941 * "data". On exit, it is returned as the number of valid bytes
942 * following the beginning of the next object.
944 * Returns a pointer to the first byte past the end
945 * of this object (i.e. the start of the next object).
946 * Returns NULL on any error.
949 asn_build_bitstring(u_char
* data
, int *datalength
,
950 u_char type
, u_char
* string
, int strlength
)
951 /* u_char *data; IN - pointer to start of object */
952 /* int *datalength; IN/OUT - # of valid bytes left in buf */
953 /* u_char type; IN - ASN type of string */
954 /* u_char *string; IN - pointer to start of input buffer */
955 /* int strlength; IN - size of input buffer */
958 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
960 if ((strlength
< 1) || ((*(char *) string
) < 0) || ((*string
) > 7)) {
961 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
964 data
= asn_build_header_with_truth(data
, datalength
, type
, strlength
, 1);
968 if (*datalength
< strlength
) {
969 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
972 memcpy((char *) data
, (char *) string
, strlength
);
973 *datalength
-= strlength
;
974 return (data
+ strlength
);
980 * To do: Write an asn_parse_exception function to go with the new
981 * asn_build_exception function below so that the exceptional values can
982 * be handled in input packets aswell as output ones.
986 * asn_build_exception - Builds an ASN exception object.
987 * On entry, datalength is input as the number of valid bytes following
988 * "data". On exit, it is returned as the number of valid bytes
989 * following the beginning of the next object.
991 * Returns a pointer to the first byte past the end
992 * of this object (i.e. the start of the next object).
993 * Returns NULL on any error.
995 * ASN.1 variable exception ::= 0x8i 0x00, where 'i' is one of these
996 * exception identifiers:
998 * 1 -- noSuchInstance
1002 asn_build_exception(u_char
* data
, int *datalength
, u_char type
)
1003 /* u_char *data; IN - pointer to start of object */
1004 /* int *datalength; IN/OUT - # of valid bytes left in buf */
1005 /* u_char type; IN - ASN type of object */
1007 return (asn_build_header_with_truth(data
, datalength
, type
, 0, 1));