]>
git.ipfire.org Git - thirdparty/squid.git/blob - 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"
88 asn_build_header(u_char
* data
, /* IN - ptr to start of object */
89 int *datalength
, /* IN/OUT - # of valid bytes */
91 u_char type
, /* IN - ASN type of object */
93 { /* IN - length of object */
94 /* Truth is 0 'cause we don't know yet */
95 return (asn_build_header_with_truth(data
, datalength
, type
, length
, 0));
100 * asn_parse_int - pulls an int out of an ASN int type.
101 * On entry, datalength is input as the number of valid bytes following
102 * "data". On exit, it is returned as the number of valid bytes
103 * following the end of this object.
105 * Returns a pointer to the first byte past the end
106 * of this object (i.e. the start of the next object).
107 * Returns NULL on any error.
110 asn_parse_int(u_char
* data
, int *datalength
,
111 u_char
* type
, int *intp
, int intsize
)
112 /* u_char *data; IN - pointer to start of object */
113 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
114 /* u_char *type; OUT - asn type of object */
115 /* int *intp; IN/OUT - pointer to start of output buffer */
116 /* int intsize; IN - size of output buffer */
119 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
125 /* Room to store int? */
126 if (intsize
!= sizeof(int)) {
127 snmp_set_api_error(SNMPERR_ASN_DECODE
);
134 bufp
= asn_parse_length(bufp
, &asn_length
);
138 /* Make sure the entire int is in the buffer */
139 if (asn_length
+ (bufp
- data
) > *datalength
) {
140 snmp_set_api_error(SNMPERR_ASN_DECODE
);
143 /* Can we store this int? */
144 if (asn_length
> intsize
) {
145 snmp_set_api_error(SNMPERR_ASN_DECODE
);
149 *datalength
-= (int) asn_length
+ (bufp
- data
);
151 /* Is the int negative? */
153 value
= -1; /* integer is negative */
155 /* Extract the bytes */
157 value
= (value
<< 8) | *bufp
++;
165 * asn_parse_unsigned_int - pulls an unsigned int out of an ASN int type.
166 * On entry, datalength is input as the number of valid bytes following
167 * "data". On exit, it is returned as the number of valid bytes
168 * following the end of this object.
170 * Returns a pointer to the first byte past the end
171 * of this object (i.e. the start of the next object).
172 * Returns NULL on any error.
175 asn_parse_unsigned_int(u_char
* data
, int *datalength
,
176 u_char
* type
, u_int
* intp
, int intsize
)
177 /* u_char *data; IN - pointer to start of object */
178 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
179 /* u_char *type; OUT - asn type of object */
180 /* u_int *intp; IN/OUT - pointer to start of output buffer */
181 /* int intsize; IN - size of output buffer */
184 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
190 /* Room to store int? */
191 if (intsize
!= sizeof(int)) {
192 snmp_set_api_error(SNMPERR_ASN_DECODE
);
199 bufp
= asn_parse_length(bufp
, &asn_length
);
203 /* Make sure the entire int is in the buffer */
204 if (asn_length
+ (bufp
- data
) > *datalength
) {
205 snmp_set_api_error(SNMPERR_ASN_DECODE
);
208 /* Can we store this int? */
209 if ((asn_length
> (intsize
+ 1)) ||
210 ((asn_length
== intsize
+ 1) && *bufp
!= 0x00)) {
211 snmp_set_api_error(SNMPERR_ASN_DECODE
);
215 *datalength
-= (int) asn_length
+ (bufp
- data
);
217 /* Is the int negative? */
219 value
= -1; /* integer is negative */
221 /* Extract the bytes */
223 value
= (value
<< 8) | *bufp
++;
231 * asn_build_int - builds an ASN object containing an integer.
232 * On entry, datalength is input as the number of valid bytes following
233 * "data". On exit, it is returned as the number of valid bytes
234 * following the end of this object.
236 * Returns a pointer to the first byte past the end
237 * of this object (i.e. the start of the next object).
238 * Returns NULL on any error.
241 asn_build_int(u_char
* data
, int *datalength
,
242 u_char type
, int *intp
, int intsize
)
243 /* u_char *data; IN - pointer to start of output buffer */
244 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
245 /* u_char type; IN - asn type of object */
246 /* int *intp; IN - pointer to start of integer */
247 /* int intsize; IN - size of *intp */
250 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
255 if (intsize
!= sizeof(int)) {
256 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
262 * Truncate "unnecessary" bytes off of the most significant end of this
263 * 2's complement integer. There should be no sequence of 9
264 * consecutive 1's or 0's at the most significant end of the
267 mask
= (u_int
) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
268 /* mask is 0xFF800000 on a big-endian machine */
270 while ((((integer
& mask
) == 0) || ((integer
& mask
) == mask
))
276 data
= asn_build_header_with_truth(data
, datalength
, type
, intsize
, 1);
280 /* Enough room for what we just encoded? */
281 if (*datalength
< intsize
) {
282 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
286 *datalength
-= intsize
;
287 mask
= (u_int
) 0xFF << (8 * (sizeof(int) - 1));
288 /* mask is 0xFF000000 on a big-endian machine */
290 *data
++ = (u_char
) ((integer
& mask
) >> (8 * (sizeof(int) - 1)));
297 * asn_build_unsigned_int - builds an ASN object containing an integer.
298 * On entry, datalength is input as the number of valid bytes following
299 * "data". On exit, it is returned as the number of valid bytes
300 * following the end of this object.
302 * Returns a pointer to the first byte past the end
303 * of this object (i.e. the start of the next object).
304 * Returns NULL on any error.
307 asn_build_unsigned_int(u_char
* data
, int *datalength
,
308 u_char type
, u_int
* intp
, int intsize
)
309 /* u_char *data; IN - pointer to start of output buffer */
310 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
311 /* u_char type; IN - asn type of object */
312 /* u_int *intp; IN - pointer to start of integer */
313 /* int intsize; IN - size of *intp */
316 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
320 int add_null_byte
= 0;
322 if (intsize
!= sizeof(int)) {
323 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
327 mask
= (u_int
) 0x80 << (8 * (sizeof(int) - 1));
328 /* mask is 0x80000000 on a big-endian machine */
329 if ((integer
& mask
) != 0) {
330 /* add a null byte if MSB is set, to prevent sign extension */
335 * Truncate "unnecessary" bytes off of the most significant end of
336 * this 2's complement integer.
337 * There should be no sequence of 9 consecutive 1's or 0's at the
338 * most significant end of the integer.
339 * The 1's case is taken care of above by adding a null byte.
341 mask
= (u_int
) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
342 /* mask is 0xFF800000 on a big-endian machine */
343 while (((integer
& mask
) == 0) && intsize
> 1) {
348 data
= asn_build_header_with_truth(data
, datalength
, type
, intsize
, 1);
352 if (*datalength
< intsize
) {
353 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
356 *datalength
-= intsize
;
357 if (add_null_byte
== 1) {
361 mask
= (u_int
) 0xFF << (8 * (sizeof(int) - 1));
362 /* mask is 0xFF000000 on a big-endian machine */
364 *data
++ = (u_char
) ((integer
& mask
) >> (8 * (sizeof(int) - 1)));
371 * asn_parse_string - pulls an octet string out of an ASN octet string type.
372 * On entry, datalength is input as the number of valid bytes following
373 * "data". On exit, it is returned as the number of valid bytes
374 * following the beginning of the next object.
376 * "string" is filled with the octet string.
378 * Returns a pointer to the first byte past the end
379 * of this object (i.e. the start of the next object).
380 * Returns NULL on any error.
383 asn_parse_string(u_char
* data
, int *datalength
,
384 u_char
* type
, u_char
* string
, int *strlength
)
385 /* u_char *data; IN - pointer to start of object */
386 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
387 /* u_char *type; OUT - asn type of object */
388 /* u_char *string; IN/OUT - pointer to start of output buffer */
389 /* int *strlength; IN/OUT - size of output buffer */
392 * ASN.1 octet string ::= primstring | cmpdstring
393 * primstring ::= 0x04 asnlength byte {byte}*
394 * cmpdstring ::= 0x24 asnlength string {string}*
400 bufp
= asn_parse_length(bufp
, &asn_length
);
404 if (asn_length
+ (bufp
- data
) > *datalength
) {
405 snmp_set_api_error(SNMPERR_ASN_DECODE
);
408 if (asn_length
> *strlength
) {
409 snmp_set_api_error(SNMPERR_ASN_DECODE
);
412 memcpy((char *) string
, (char *) bufp
, (int) asn_length
);
413 *strlength
= (int) asn_length
;
414 *datalength
-= (int) asn_length
+ (bufp
- data
);
415 return (bufp
+ asn_length
);
419 * asn_build_string - Builds an ASN octet string object containing the input
420 * string. On entry, datalength is input as the number of valid bytes
421 * following "data". On exit, it is returned as the number of valid bytes
422 * following the beginning of the next object.
424 * Returns a pointer to the first byte past the end
425 * of this object (i.e. the start of the next object).
426 * Returns NULL on any error.
429 asn_build_string(u_char
* data
, int *datalength
,
430 u_char type
, u_char
* string
, int strlength
)
431 /* u_char *data; IN - pointer to start of object */
432 /* int *datalength; IN/OUT - # of valid bytes left in buf */
433 /* u_char type; IN - ASN type of string */
434 /* u_char *string; IN - pointer to start of input buffer */
435 /* int strlength; IN - size of input buffer */
438 * ASN.1 octet string ::= primstring | cmpdstring
439 * primstring ::= 0x04 asnlength byte {byte}*
440 * cmpdstring ::= 0x24 asnlength string {string}*
441 * This code will never send a compound string.
443 data
= asn_build_header_with_truth(data
, datalength
, type
, strlength
, 1);
447 if (*datalength
< strlength
) {
448 snmp_set_api_error(SNMPERR_ASN_DECODE
);
451 memcpy((char *) data
, (char *) string
, strlength
);
452 *datalength
-= strlength
;
453 return (data
+ strlength
);
458 * asn_parse_header - interprets the ID and length of the current object.
459 * On entry, datalength is input as the number of valid bytes following
460 * "data". On exit, it is returned as the number of valid bytes
461 * in this object following the id and length.
463 * Returns a pointer to the first byte of the contents of this object.
464 * Returns NULL on any error.
467 asn_parse_header(u_char
* data
, int *datalength
, u_char
* type
)
468 /* u_char *data; IN - pointer to start of object */
469 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
470 /* u_char *type; OUT - ASN type of object */
476 /* this only works on data types < 30, i.e. no extension octets */
477 if (IS_EXTENSION_ID(*bufp
)) {
478 snmp_set_api_error(SNMPERR_ASN_DECODE
);
482 bufp
= asn_parse_length(bufp
+ 1, &asn_length
);
486 header_len
= bufp
- data
;
487 if (header_len
+ asn_length
> *datalength
|| asn_length
> (u_int
)(2 << 18) ) {
488 snmp_set_api_error(SNMPERR_ASN_DECODE
);
491 *datalength
= (int) asn_length
;
496 * asn_build_header - builds an ASN header for an object with the ID and
498 * On entry, datalength is input as the number of valid bytes following
499 * "data". On exit, it is returned as the number of valid bytes
500 * in this object following the id and length.
502 * This only works on data types < 30, i.e. no extension octets.
503 * The maximum length is 0xFFFF;
505 * Returns a pointer to the first byte of the contents of this object.
506 * Returns NULL on any error.
510 asn_build_header_with_truth(u_char
* data
, int *datalength
,
511 u_char type
, int length
, int truth
)
512 /* u_char *data; IN - pointer to start of object */
513 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
514 /* u_char type; IN - ASN type of object */
515 /* int length; IN - length of object */
516 /* int truth; IN - Whether length is truth */
518 if (*datalength
< 1) {
519 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
524 return (asn_build_length(data
, datalength
, length
, truth
));
529 * asn_build_sequence - builds an ASN header for a sequence with the ID and
531 * On entry, datalength is input as the number of valid bytes following
532 * "data". On exit, it is returned as the number of valid bytes
533 * in this object following the id and length.
535 * This only works on data types < 30, i.e. no extension octets.
536 * The maximum length is 0xFFFF;
538 * Returns a pointer to the first byte of the contents of this object.
539 * Returns NULL on any error.
542 asn_build_sequence(u_char
* data
, int *datalength
,
543 u_char type
, int length
)
544 /* u_char *data; IN - pointer to start of object */
545 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
546 /* u_char type; IN - ASN type of object */
547 /* int length; IN - length of object */
550 if (*datalength
< 0) {
551 *datalength
+= 4; /* fix up before punting */
552 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
556 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
557 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
558 *data
++ = (u_char
) (length
& 0xFF);
564 * asn_parse_length - interprets the length of the current object.
565 * On exit, length contains the value of this length field.
567 * Returns a pointer to the first byte after this length
568 * field (aka: the start of the data field).
569 * Returns NULL on any error.
572 asn_parse_length(u_char
* data
, u_int
* length
)
573 /* u_char *data; IN - pointer to start of length field */
574 /* u_int *length; OUT - value of length field */
576 u_char lengthbyte
= *data
;
578 if (lengthbyte
& ASN_LONG_LEN
) {
579 lengthbyte
&= ~ASN_LONG_LEN
; /* turn MSb off */
581 if (lengthbyte
== 0) {
582 snmp_set_api_error(SNMPERR_ASN_DECODE
);
585 if (lengthbyte
> sizeof(int)) {
586 snmp_set_api_error(SNMPERR_ASN_DECODE
);
590 memcpy((char *) (length
), (char *) data
+ 1, (int) lengthbyte
);
591 *length
= ntohl(*length
);
592 *length
>>= (8 * ((sizeof *length
) - lengthbyte
));
593 return (data
+ lengthbyte
+ 1);
596 /* short asnlength */
598 *length
= (int) lengthbyte
;
604 asn_build_length(u_char
* data
, int *datalength
,
605 int length
, int truth
)
606 /* u_char *data; IN - pointer to start of object */
607 /* int *datalength; IN/OUT - # of valid bytes left in buf */
608 /* int length; IN - length of object */
609 /* int truth; IN - If 1, this is the true len. */
611 u_char
*start_data
= data
;
615 /* no indefinite lengths sent */
617 if (*datalength
< 1) {
618 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
621 *data
++ = (u_char
) length
;
623 } else if (length
<= 0xFF) {
624 if (*datalength
< 2) {
625 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
628 *data
++ = (u_char
) (0x01 | ASN_LONG_LEN
);
629 *data
++ = (u_char
) length
;
630 } else { /* 0xFF < length <= 0xFFFF */
631 if (*datalength
< 3) {
632 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
635 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
636 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
637 *data
++ = (u_char
) (length
& 0xFF);
642 /* Don't know if this is the true length. Make sure it's large
645 if (*datalength
< 3) {
646 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
649 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
650 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
651 *data
++ = (u_char
) (length
& 0xFF);
654 *datalength
-= (data
- start_data
);
659 * asn_parse_objid - pulls an object indentifier out of an ASN object
661 * On entry, datalength is input as the number of valid bytes following
662 * "data". On exit, it is returned as the number of valid bytes
663 * following the beginning of the next object.
665 * "objid" is filled with the object identifier.
667 * Returns a pointer to the first byte past the end
668 * of this object (i.e. the start of the next object).
669 * Returns NULL on any error.
672 asn_parse_objid(u_char
* data
, int *datalength
,
673 u_char
* type
, oid
* objid
, int *objidlength
)
674 /* u_char *data; IN - pointer to start of object */
675 /* int *datalength; IN/OUT - # of valid bytes left in buf */
676 /* u_char *type; OUT - ASN type of object */
677 /* oid *objid; IN/OUT - pointer to start of output buffer */
678 /* int *objidlength; IN/OUT - number of sub-id's in objid */
681 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
682 * subidentifier ::= {leadingbyte}* lastbyte
683 * leadingbyte ::= 1 7bitvalue
684 * lastbyte ::= 0 7bitvalue
687 oid
*oidp
= objid
+ 1;
693 bufp
= asn_parse_length(bufp
, &asn_length
);
697 if (asn_length
+ (bufp
- data
) > *datalength
) {
698 snmp_set_api_error(SNMPERR_ASN_DECODE
);
701 *datalength
-= (int) asn_length
+ (bufp
- data
);
703 /* Handle invalid object identifier encodings of the form 06 00 robustly */
705 objid
[0] = objid
[1] = 0;
708 (*objidlength
)--; /* account for expansion of first byte */
709 while (length
> 0 && (*objidlength
)-- > 0) {
712 do { /* shift and add in low order 7 bits */
713 subidentifier
= (subidentifier
<< 7)
714 + (*(u_char
*) bufp
& ~ASN_BIT8
);
716 } while (*(u_char
*) bufp
++ & ASN_BIT8
);
718 /* while last byte has high bit clear */
719 if (subidentifier
> (u_int
) MAX_SUBID
) {
720 snmp_set_api_error(SNMPERR_ASN_DECODE
);
723 *oidp
++ = (oid
) subidentifier
;
727 * The first two subidentifiers are encoded into the first component
728 * with the value (X * 40) + Y, where:
729 * X is the value of the first subidentifier.
730 * Y is the value of the second subidentifier.
732 subidentifier
= (u_int
) objid
[1];
733 if (subidentifier
== 0x2B) {
737 objid
[1] = (u_char
) (subidentifier
% 40);
738 objid
[0] = (u_char
) ((subidentifier
- objid
[1]) / 40);
741 *objidlength
= (int) (oidp
- objid
);
746 * asn_build_objid - Builds an ASN object identifier object containing the
748 * On entry, datalength is input as the number of valid bytes following
749 * "data". On exit, it is returned as the number of valid bytes
750 * following the beginning of the next object.
752 * Returns a pointer to the first byte past the end
753 * of this object (i.e. the start of the next object).
754 * Returns NULL on any error.
757 asn_build_objid(u_char
* data
, int *datalength
,
758 u_char type
, oid
* objid
, int objidlength
)
759 /* u_char *data; IN - pointer to start of object */
760 /* int *datalength; IN/OUT - # of valid bytes left in buf */
761 /* u_char type; IN - ASN type of object */
762 /* oid *objid; IN - pointer to start of input buffer */
763 /* int objidlength; IN - number of sub-id's in objid */
766 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
767 * subidentifier ::= {leadingbyte}* lastbyte
768 * leadingbyte ::= 1 7bitvalue
769 * lastbyte ::= 0 7bitvalue
771 u_char buf
[MAX_OID_LEN
];
775 u_int subid
, mask
, testmask
;
778 if (objidlength
< 2) {
782 *bp
++ = op
[1] + (op
[0] * 40);
787 while (objidlength
-- > 0) {
789 if (subid
< 127) { /* off by one? */
792 mask
= 0x7F; /* handle subid == 0 case */
794 /* testmask *MUST* !!!! be of an unsigned type */
795 for (testmask
= 0x7F, testbits
= 0; testmask
!= 0;
796 testmask
<<= 7, testbits
+= 7) {
797 if (subid
& testmask
) { /* if any bits set */
802 /* mask can't be zero here */
803 for (; mask
!= 0x7F; mask
>>= 7, bits
-= 7) {
804 /* fix a mask that got truncated above */
805 if (mask
== 0x1E00000)
807 *bp
++ = (u_char
) (((subid
& mask
) >> bits
) | ASN_BIT8
);
809 *bp
++ = (u_char
) (subid
& mask
);
813 asnlength
= bp
- buf
;
814 data
= asn_build_header_with_truth(data
, datalength
, type
, asnlength
, 1);
817 if (*datalength
< asnlength
) {
818 snmp_set_api_error(SNMPERR_ASN_DECODE
);
821 memcpy((char *) data
, (char *) buf
, asnlength
);
822 *datalength
-= asnlength
;
823 return (data
+ asnlength
);
828 * asn_parse_null - Interprets an ASN null type.
829 * On entry, datalength is input as the number of valid bytes following
830 * "data". On exit, it is returned as the number of valid bytes
831 * following the beginning of the next object.
833 * Returns a pointer to the first byte past the end
834 * of this object (i.e. the start of the next object).
835 * Returns NULL on any error.
838 asn_parse_null(u_char
* data
, int *datalength
, u_char
* type
)
839 /* u_char *data; IN - pointer to start of object */
840 /* int *datalength; IN/OUT - # of valid bytes left in buf */
841 /* u_char *type; OUT - ASN type of object */
844 * ASN.1 null ::= 0x05 0x00
850 bufp
= asn_parse_length(bufp
, &asn_length
);
854 if (asn_length
!= 0) {
855 snmp_set_api_error(SNMPERR_ASN_DECODE
);
858 *datalength
-= (bufp
- data
);
859 return (bufp
+ asn_length
);
864 * asn_build_null - Builds an ASN null object.
865 * On entry, datalength is input as the number of valid bytes following
866 * "data". On exit, it is returned as the number of valid bytes
867 * following the beginning of the next object.
869 * Returns a pointer to the first byte past the end
870 * of this object (i.e. the start of the next object).
871 * Returns NULL on any error.
874 asn_build_null(u_char
* data
, int *datalength
, u_char type
)
875 /* u_char *data; IN - pointer to start of object */
876 /* int *datalength; IN/OUT - # of valid bytes left in buf */
877 /* u_char type; IN - ASN type of object */
880 * ASN.1 null ::= 0x05 0x00
882 return (asn_build_header_with_truth(data
, datalength
, type
, 0, 1));
888 * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type.
889 * On entry, datalength is input as the number of valid bytes following
890 * "data". On exit, it is returned as the number of valid bytes
891 * following the beginning of the next object.
893 * "string" is filled with the bit string.
895 * Returns a pointer to the first byte past the end
896 * of this object (i.e. the start of the next object).
897 * Returns NULL on any error.
900 asn_parse_bitstring(u_char
* data
, int *datalength
,
901 u_char
* type
, u_char
* string
, int *strlength
)
902 /* u_char *data; IN - pointer to start of object */
903 /* int *datalength; IN/OUT - # of valid bytes left in buf */
904 /* u_char *type; OUT - asn type of object */
905 /* u_char *string; IN/OUT - pointer to start of output buf */
906 /* int *strlength; IN/OUT - size of output buffer */
909 * bitstring ::= 0x03 asnlength unused {byte}*
915 bufp
= asn_parse_length(bufp
, &asn_length
);
919 if (asn_length
+ (bufp
- data
) > *datalength
) {
920 snmp_set_api_error(SNMPERR_ASN_DECODE
);
923 if (asn_length
> *strlength
) {
924 snmp_set_api_error(SNMPERR_ASN_DECODE
);
927 if (asn_length
< 1) {
928 snmp_set_api_error(SNMPERR_ASN_DECODE
);
931 if ((int) (*(char *) bufp
) < 0 || (int) (*bufp
) > 7) {
932 snmp_set_api_error(SNMPERR_ASN_DECODE
);
935 memcpy((char *) string
, (char *) bufp
, (int) asn_length
);
936 *strlength
= (int) asn_length
;
937 *datalength
-= (int) asn_length
+ (bufp
- data
);
938 return (bufp
+ asn_length
);
942 * asn_build_bitstring - Builds an ASN bit string object containing the
944 * On entry, datalength is input as the number of valid bytes following
945 * "data". On exit, it is returned as the number of valid bytes
946 * following the beginning of the next object.
948 * Returns a pointer to the first byte past the end
949 * of this object (i.e. the start of the next object).
950 * Returns NULL on any error.
953 asn_build_bitstring(u_char
* data
, int *datalength
,
954 u_char type
, u_char
* string
, int strlength
)
955 /* u_char *data; IN - pointer to start of object */
956 /* int *datalength; IN/OUT - # of valid bytes left in buf */
957 /* u_char type; IN - ASN type of string */
958 /* u_char *string; IN - pointer to start of input buffer */
959 /* int strlength; IN - size of input buffer */
962 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
964 if ((strlength
< 1) || ((*(char *) string
) < 0) || ((*string
) > 7)) {
965 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
968 data
= asn_build_header_with_truth(data
, datalength
, type
, strlength
, 1);
972 if (*datalength
< strlength
) {
973 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
976 memcpy((char *) data
, (char *) string
, strlength
);
977 *datalength
-= strlength
;
978 return (data
+ strlength
);
984 * To do: Write an asn_parse_exception function to go with the new
985 * asn_build_exception function below so that the exceptional values can
986 * be handled in input packets aswell as output ones.
990 * asn_build_exception - Builds an ASN exception object.
991 * On entry, datalength is input as the number of valid bytes following
992 * "data". On exit, it is returned as the number of valid bytes
993 * following the beginning of the next object.
995 * Returns a pointer to the first byte past the end
996 * of this object (i.e. the start of the next object).
997 * Returns NULL on any error.
999 * ASN.1 variable exception ::= 0x8i 0x00, where 'i' is one of these
1000 * exception identifiers:
1002 * 1 -- noSuchInstance
1006 asn_build_exception(u_char
* data
, int *datalength
, u_char type
)
1007 /* u_char *data; IN - pointer to start of object */
1008 /* int *datalength; IN/OUT - # of valid bytes left in buf */
1009 /* u_char type; IN - ASN type of object */
1011 return (asn_build_header_with_truth(data
, datalength
, type
, 0, 1));