]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/snmplib/asn1.c
8b37165952d09fc1778654f8fe5058c78a61752c
2 * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 * Abstract Syntax Notation One, ASN.1
11 * As defined in ISO/IS 8824 and ISO/IS 8825
12 * This implements a subset of the above International Standards that
13 * is sufficient to implement SNMP.
15 * Encodes abstract data types into a machine independent stream of bytes.
18 /***************************************************************************
20 * Copyright 1997 by Carnegie Mellon University
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation for any purpose and without fee is hereby granted,
26 * provided that the above copyright notice appear in all copies and that
27 * both that copyright notice and this permission notice appear in
28 * supporting documentation, and that the name of CMU not be
29 * used in advertising or publicity pertaining to distribution of the
30 * software without specific, written prior permission.
32 * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
33 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
34 * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
35 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
36 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
37 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
40 ***************************************************************************/
51 #include <sys/types.h>
57 #include <gnumalloc.h>
74 #include <sys/socket.h>
77 #include <netinet/in.h>
80 #include <arpa/inet.h>
90 #include "snmp_api_error.h"
93 asn_build_header(u_char
* data
, /* IN - ptr to start of object */
94 int *datalength
, /* IN/OUT - # of valid bytes */
96 u_char type
, /* IN - ASN type of object */
98 { /* IN - length of object */
99 /* Truth is 0 'cause we don't know yet */
100 return (asn_build_header_with_truth(data
, datalength
, type
, length
, 0));
104 * asn_parse_int - pulls an int out of an ASN int type.
105 * On entry, datalength is input as the number of valid bytes following
106 * "data". On exit, it is returned as the number of valid bytes
107 * following the end of this object.
109 * Returns a pointer to the first byte past the end
110 * of this object (i.e. the start of the next object).
111 * Returns NULL on any error.
114 asn_parse_int(u_char
* data
, int *datalength
,
115 u_char
* type
, int *intp
, int intsize
)
116 /* u_char *data; IN - pointer to start of object */
117 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
118 /* u_char *type; OUT - asn type of object */
119 /* int *intp; IN/OUT - pointer to start of output buffer */
120 /* int intsize; IN - size of output buffer */
123 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
129 /* Room to store int? */
130 if (intsize
!= sizeof(int)) {
131 snmp_set_api_error(SNMPERR_ASN_DECODE
);
138 bufp
= asn_parse_length(bufp
, &asn_length
);
142 /* Make sure the entire int is in the buffer */
143 if (asn_length
+ (bufp
- data
) > *datalength
) {
144 snmp_set_api_error(SNMPERR_ASN_DECODE
);
147 /* Can we store this int? */
148 if (asn_length
> intsize
) {
149 snmp_set_api_error(SNMPERR_ASN_DECODE
);
153 *datalength
-= (int) asn_length
+ (bufp
- data
);
155 /* Is the int negative? */
157 value
= -1; /* integer is negative */
159 /* Extract the bytes */
161 value
= (value
<< 8) | *bufp
++;
169 * asn_parse_unsigned_int - pulls an unsigned int out of an ASN int type.
170 * On entry, datalength is input as the number of valid bytes following
171 * "data". On exit, it is returned as the number of valid bytes
172 * following the end of this object.
174 * Returns a pointer to the first byte past the end
175 * of this object (i.e. the start of the next object).
176 * Returns NULL on any error.
179 asn_parse_unsigned_int(u_char
* data
, int *datalength
,
180 u_char
* type
, u_int
* intp
, int intsize
)
181 /* u_char *data; IN - pointer to start of object */
182 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
183 /* u_char *type; OUT - asn type of object */
184 /* u_int *intp; IN/OUT - pointer to start of output buffer */
185 /* int intsize; IN - size of output buffer */
188 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
194 /* Room to store int? */
195 if (intsize
!= sizeof(int)) {
196 snmp_set_api_error(SNMPERR_ASN_DECODE
);
203 bufp
= asn_parse_length(bufp
, &asn_length
);
207 /* Make sure the entire int is in the buffer */
208 if (asn_length
+ (bufp
- data
) > *datalength
) {
209 snmp_set_api_error(SNMPERR_ASN_DECODE
);
212 /* Can we store this int? */
213 if ((asn_length
> (intsize
+ 1)) ||
214 ((asn_length
== intsize
+ 1) && *bufp
!= 0x00)) {
215 snmp_set_api_error(SNMPERR_ASN_DECODE
);
219 *datalength
-= (int) asn_length
+ (bufp
- data
);
221 /* Is the int negative? */
223 value
= -1; /* integer is negative */
225 /* Extract the bytes */
227 value
= (value
<< 8) | *bufp
++;
235 * asn_build_int - builds an ASN object containing an integer.
236 * On entry, datalength is input as the number of valid bytes following
237 * "data". On exit, it is returned as the number of valid bytes
238 * following the end of this object.
240 * Returns a pointer to the first byte past the end
241 * of this object (i.e. the start of the next object).
242 * Returns NULL on any error.
245 asn_build_int(u_char
* data
, int *datalength
,
246 u_char type
, int *intp
, int intsize
)
247 /* u_char *data; IN - pointer to start of output buffer */
248 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
249 /* u_char type; IN - asn type of object */
250 /* int *intp; IN - pointer to start of integer */
251 /* int intsize; IN - size of *intp */
254 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
259 if (intsize
!= sizeof(int)) {
260 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
266 * Truncate "unnecessary" bytes off of the most significant end of this
267 * 2's complement integer. There should be no sequence of 9
268 * consecutive 1's or 0's at the most significant end of the
271 mask
= (u_int
) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
272 /* mask is 0xFF800000 on a big-endian machine */
274 while ((((integer
& mask
) == 0) || ((integer
& mask
) == mask
))
280 data
= asn_build_header_with_truth(data
, datalength
, type
, intsize
, 1);
284 /* Enough room for what we just encoded? */
285 if (*datalength
< intsize
) {
286 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
290 *datalength
-= intsize
;
291 mask
= (u_int
) 0xFF << (8 * (sizeof(int) - 1));
292 /* mask is 0xFF000000 on a big-endian machine */
294 *data
++ = (u_char
) ((integer
& mask
) >> (8 * (sizeof(int) - 1)));
301 * asn_build_unsigned_int - builds an ASN object containing an integer.
302 * On entry, datalength is input as the number of valid bytes following
303 * "data". On exit, it is returned as the number of valid bytes
304 * following the end of this object.
306 * Returns a pointer to the first byte past the end
307 * of this object (i.e. the start of the next object).
308 * Returns NULL on any error.
311 asn_build_unsigned_int(u_char
* data
, int *datalength
,
312 u_char type
, u_int
* intp
, int intsize
)
313 /* u_char *data; IN - pointer to start of output buffer */
314 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
315 /* u_char type; IN - asn type of object */
316 /* u_int *intp; IN - pointer to start of integer */
317 /* int intsize; IN - size of *intp */
320 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
324 int add_null_byte
= 0;
326 if (intsize
!= sizeof(int)) {
327 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
331 mask
= (u_int
) 0x80 << (8 * (sizeof(int) - 1));
332 /* mask is 0x80000000 on a big-endian machine */
333 if ((integer
& mask
) != 0) {
334 /* add a null byte if MSB is set, to prevent sign extension */
339 * Truncate "unnecessary" bytes off of the most significant end of
340 * this 2's complement integer.
341 * There should be no sequence of 9 consecutive 1's or 0's at the
342 * most significant end of the integer.
343 * The 1's case is taken care of above by adding a null byte.
345 mask
= (u_int
) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
346 /* mask is 0xFF800000 on a big-endian machine */
347 while (((integer
& mask
) == 0) && intsize
> 1) {
352 data
= asn_build_header_with_truth(data
, datalength
, type
, intsize
, 1);
356 if (*datalength
< intsize
) {
357 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
360 *datalength
-= intsize
;
361 if (add_null_byte
== 1) {
365 mask
= (u_int
) 0xFF << (8 * (sizeof(int) - 1));
366 /* mask is 0xFF000000 on a big-endian machine */
368 *data
++ = (u_char
) ((integer
& mask
) >> (8 * (sizeof(int) - 1)));
375 * asn_parse_string - pulls an octet string out of an ASN octet string type.
376 * On entry, datalength is input as the number of valid bytes following
377 * "data". On exit, it is returned as the number of valid bytes
378 * following the beginning of the next object.
380 * "string" is filled with the octet string.
382 * Returns a pointer to the first byte past the end
383 * of this object (i.e. the start of the next object).
384 * Returns NULL on any error.
387 asn_parse_string(u_char
* data
, int *datalength
,
388 u_char
* type
, u_char
* string
, int *strlength
)
389 /* u_char *data; IN - pointer to start of object */
390 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
391 /* u_char *type; OUT - asn type of object */
392 /* u_char *string; IN/OUT - pointer to start of output buffer */
393 /* int *strlength; IN/OUT - size of output buffer */
396 * ASN.1 octet string ::= primstring | cmpdstring
397 * primstring ::= 0x04 asnlength byte {byte}*
398 * cmpdstring ::= 0x24 asnlength string {string}*
404 bufp
= asn_parse_length(bufp
, &asn_length
);
408 if (asn_length
+ (bufp
- data
) > *datalength
) {
409 snmp_set_api_error(SNMPERR_ASN_DECODE
);
412 if (asn_length
> *strlength
) {
413 snmp_set_api_error(SNMPERR_ASN_DECODE
);
416 memcpy((char *) string
, (char *) bufp
, (int) asn_length
);
417 *strlength
= (int) asn_length
;
418 *datalength
-= (int) asn_length
+ (bufp
- data
);
419 return (bufp
+ asn_length
);
423 * asn_build_string - Builds an ASN octet string object containing the input
424 * string. On entry, datalength is input as the number of valid bytes
425 * following "data". On exit, it is returned as the number of valid bytes
426 * following the beginning of the next object.
428 * Returns a pointer to the first byte past the end
429 * of this object (i.e. the start of the next object).
430 * Returns NULL on any error.
433 asn_build_string(u_char
* data
, int *datalength
,
434 u_char type
, u_char
* string
, int strlength
)
435 /* u_char *data; IN - pointer to start of object */
436 /* int *datalength; IN/OUT - # of valid bytes left in buf */
437 /* u_char type; IN - ASN type of string */
438 /* u_char *string; IN - pointer to start of input buffer */
439 /* int strlength; IN - size of input buffer */
442 * ASN.1 octet string ::= primstring | cmpdstring
443 * primstring ::= 0x04 asnlength byte {byte}*
444 * cmpdstring ::= 0x24 asnlength string {string}*
445 * This code will never send a compound string.
447 data
= asn_build_header_with_truth(data
, datalength
, type
, strlength
, 1);
451 if (*datalength
< strlength
) {
452 snmp_set_api_error(SNMPERR_ASN_DECODE
);
455 memcpy((char *) data
, (char *) string
, strlength
);
456 *datalength
-= strlength
;
457 return (data
+ strlength
);
461 * asn_parse_header - interprets the ID and length of the current object.
462 * On entry, datalength is input as the number of valid bytes following
463 * "data". On exit, it is returned as the number of valid bytes
464 * in this object following the id and length.
466 * Returns a pointer to the first byte of the contents of this object.
467 * Returns NULL on any error.
470 asn_parse_header(u_char
* data
, int *datalength
, u_char
* type
)
471 /* u_char *data; IN - pointer to start of object */
472 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
473 /* u_char *type; OUT - ASN type of object */
479 /* this only works on data types < 30, i.e. no extension octets */
480 if (IS_EXTENSION_ID(*bufp
)) {
481 snmp_set_api_error(SNMPERR_ASN_DECODE
);
485 bufp
= asn_parse_length(bufp
+ 1, &asn_length
);
489 header_len
= bufp
- data
;
490 if (header_len
+ asn_length
> *datalength
|| asn_length
> (u_int
)(2 << 18) ) {
491 snmp_set_api_error(SNMPERR_ASN_DECODE
);
494 *datalength
= (int) asn_length
;
499 * asn_build_header - builds an ASN header for an object with the ID and
501 * On entry, datalength is input as the number of valid bytes following
502 * "data". On exit, it is returned as the number of valid bytes
503 * in this object following the id and length.
505 * This only works on data types < 30, i.e. no extension octets.
506 * The maximum length is 0xFFFF;
508 * Returns a pointer to the first byte of the contents of this object.
509 * Returns NULL on any error.
513 asn_build_header_with_truth(u_char
* data
, int *datalength
,
514 u_char type
, int length
, int truth
)
515 /* u_char *data; IN - pointer to start of object */
516 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
517 /* u_char type; IN - ASN type of object */
518 /* int length; IN - length of object */
519 /* int truth; IN - Whether length is truth */
521 if (*datalength
< 1) {
522 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
527 return (asn_build_length(data
, datalength
, length
, truth
));
532 * asn_build_sequence - builds an ASN header for a sequence with the ID and
534 * On entry, datalength is input as the number of valid bytes following
535 * "data". On exit, it is returned as the number of valid bytes
536 * in this object following the id and length.
538 * This only works on data types < 30, i.e. no extension octets.
539 * The maximum length is 0xFFFF;
541 * Returns a pointer to the first byte of the contents of this object.
542 * Returns NULL on any error.
545 asn_build_sequence(u_char
* data
, int *datalength
,
546 u_char type
, int length
)
547 /* u_char *data; IN - pointer to start of object */
548 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
549 /* u_char type; IN - ASN type of object */
550 /* int length; IN - length of object */
553 if (*datalength
< 0) {
554 *datalength
+= 4; /* fix up before punting */
555 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
559 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
560 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
561 *data
++ = (u_char
) (length
& 0xFF);
567 * asn_parse_length - interprets the length of the current object.
568 * On exit, length contains the value of this length field.
570 * Returns a pointer to the first byte after this length
571 * field (aka: the start of the data field).
572 * Returns NULL on any error.
575 asn_parse_length(u_char
* data
, u_int
* length
)
576 /* u_char *data; IN - pointer to start of length field */
577 /* u_int *length; OUT - value of length field */
579 u_char lengthbyte
= *data
;
581 if (lengthbyte
& ASN_LONG_LEN
) {
582 lengthbyte
&= ~ASN_LONG_LEN
; /* turn MSb off */
584 if (lengthbyte
== 0) {
585 snmp_set_api_error(SNMPERR_ASN_DECODE
);
588 if (lengthbyte
> sizeof(int)) {
589 snmp_set_api_error(SNMPERR_ASN_DECODE
);
593 memcpy((char *) (length
), (char *) data
+ 1, (int) lengthbyte
);
594 *length
= ntohl(*length
);
595 *length
>>= (8 * ((sizeof *length
) - lengthbyte
));
596 return (data
+ lengthbyte
+ 1);
599 /* short asnlength */
601 *length
= (int) lengthbyte
;
606 asn_build_length(u_char
* data
, int *datalength
,
607 int length
, int truth
)
608 /* u_char *data; IN - pointer to start of object */
609 /* int *datalength; IN/OUT - # of valid bytes left in buf */
610 /* int length; IN - length of object */
611 /* int truth; IN - If 1, this is the true len. */
613 u_char
*start_data
= data
;
617 /* no indefinite lengths sent */
619 if (*datalength
< 1) {
620 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
623 *data
++ = (u_char
) length
;
625 } else if (length
<= 0xFF) {
626 if (*datalength
< 2) {
627 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
630 *data
++ = (u_char
) (0x01 | ASN_LONG_LEN
);
631 *data
++ = (u_char
) length
;
632 } else { /* 0xFF < length <= 0xFFFF */
633 if (*datalength
< 3) {
634 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
637 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
638 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
639 *data
++ = (u_char
) (length
& 0xFF);
644 /* Don't know if this is the true length. Make sure it's large
647 if (*datalength
< 3) {
648 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
651 *data
++ = (u_char
) (0x02 | ASN_LONG_LEN
);
652 *data
++ = (u_char
) ((length
>> 8) & 0xFF);
653 *data
++ = (u_char
) (length
& 0xFF);
656 *datalength
-= (data
- start_data
);
661 * asn_parse_objid - pulls an object indentifier out of an ASN object
663 * On entry, datalength is input as the number of valid bytes following
664 * "data". On exit, it is returned as the number of valid bytes
665 * following the beginning of the next object.
667 * "objid" is filled with the object identifier.
669 * Returns a pointer to the first byte past the end
670 * of this object (i.e. the start of the next object).
671 * Returns NULL on any error.
674 asn_parse_objid(u_char
* data
, int *datalength
,
675 u_char
* type
, oid
* objid
, int *objidlength
)
676 /* u_char *data; IN - pointer to start of object */
677 /* int *datalength; IN/OUT - # of valid bytes left in buf */
678 /* u_char *type; OUT - ASN type of object */
679 /* oid *objid; IN/OUT - pointer to start of output buffer */
680 /* int *objidlength; IN/OUT - number of sub-id's in objid */
683 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
684 * subidentifier ::= {leadingbyte}* lastbyte
685 * leadingbyte ::= 1 7bitvalue
686 * lastbyte ::= 0 7bitvalue
689 oid
*oidp
= objid
+ 1;
695 bufp
= asn_parse_length(bufp
, &asn_length
);
699 if (asn_length
+ (bufp
- data
) > *datalength
) {
700 snmp_set_api_error(SNMPERR_ASN_DECODE
);
703 *datalength
-= (int) asn_length
+ (bufp
- data
);
705 /* Handle invalid object identifier encodings of the form 06 00 robustly */
707 objid
[0] = objid
[1] = 0;
710 (*objidlength
)--; /* account for expansion of first byte */
711 while (length
> 0 && (*objidlength
)-- > 0) {
714 do { /* shift and add in low order 7 bits */
715 subidentifier
= (subidentifier
<< 7)
716 + (*(u_char
*) bufp
& ~ASN_BIT8
);
718 } while (*(u_char
*) bufp
++ & ASN_BIT8
);
720 /* while last byte has high bit clear */
721 if (subidentifier
> (u_int
) MAX_SUBID
) {
722 snmp_set_api_error(SNMPERR_ASN_DECODE
);
725 *oidp
++ = (oid
) subidentifier
;
729 * The first two subidentifiers are encoded into the first component
730 * with the value (X * 40) + Y, where:
731 * X is the value of the first subidentifier.
732 * Y is the value of the second subidentifier.
734 subidentifier
= (u_int
) objid
[1];
735 if (subidentifier
== 0x2B) {
739 objid
[1] = (u_char
) (subidentifier
% 40);
740 objid
[0] = (u_char
) ((subidentifier
- objid
[1]) / 40);
743 *objidlength
= (int) (oidp
- objid
);
748 * asn_build_objid - Builds an ASN object identifier object containing the
750 * On entry, datalength is input as the number of valid bytes following
751 * "data". On exit, it is returned as the number of valid bytes
752 * following the beginning of the next object.
754 * Returns a pointer to the first byte past the end
755 * of this object (i.e. the start of the next object).
756 * Returns NULL on any error.
759 asn_build_objid(u_char
* data
, int *datalength
,
760 u_char type
, oid
* objid
, int objidlength
)
761 /* u_char *data; IN - pointer to start of object */
762 /* int *datalength; IN/OUT - # of valid bytes left in buf */
763 /* u_char type; IN - ASN type of object */
764 /* oid *objid; IN - pointer to start of input buffer */
765 /* int objidlength; IN - number of sub-id's in objid */
768 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
769 * subidentifier ::= {leadingbyte}* lastbyte
770 * leadingbyte ::= 1 7bitvalue
771 * lastbyte ::= 0 7bitvalue
773 u_char buf
[MAX_OID_LEN
];
777 u_int subid
, mask
, testmask
;
780 if (objidlength
< 2) {
784 *bp
++ = op
[1] + (op
[0] * 40);
789 while (objidlength
-- > 0) {
791 if (subid
< 127) { /* off by one? */
794 mask
= 0x7F; /* handle subid == 0 case */
796 /* testmask *MUST* !!!! be of an unsigned type */
797 for (testmask
= 0x7F, testbits
= 0; testmask
!= 0;
798 testmask
<<= 7, testbits
+= 7) {
799 if (subid
& testmask
) { /* if any bits set */
804 /* mask can't be zero here */
805 for (; mask
!= 0x7F; mask
>>= 7, bits
-= 7) {
806 /* fix a mask that got truncated above */
807 if (mask
== 0x1E00000)
809 *bp
++ = (u_char
) (((subid
& mask
) >> bits
) | ASN_BIT8
);
811 *bp
++ = (u_char
) (subid
& mask
);
815 asnlength
= bp
- buf
;
816 data
= asn_build_header_with_truth(data
, datalength
, type
, asnlength
, 1);
819 if (*datalength
< asnlength
) {
820 snmp_set_api_error(SNMPERR_ASN_DECODE
);
823 memcpy((char *) data
, (char *) buf
, asnlength
);
824 *datalength
-= asnlength
;
825 return (data
+ asnlength
);
830 * asn_parse_null - Interprets an ASN null type.
831 * On entry, datalength is input as the number of valid bytes following
832 * "data". On exit, it is returned as the number of valid bytes
833 * following the beginning of the next object.
835 * Returns a pointer to the first byte past the end
836 * of this object (i.e. the start of the next object).
837 * Returns NULL on any error.
840 asn_parse_null(u_char
* data
, int *datalength
, u_char
* type
)
841 /* u_char *data; IN - pointer to start of object */
842 /* int *datalength; IN/OUT - # of valid bytes left in buf */
843 /* u_char *type; OUT - ASN type of object */
846 * ASN.1 null ::= 0x05 0x00
852 bufp
= asn_parse_length(bufp
, &asn_length
);
856 if (asn_length
!= 0) {
857 snmp_set_api_error(SNMPERR_ASN_DECODE
);
860 *datalength
-= (bufp
- data
);
861 return (bufp
+ asn_length
);
866 * asn_build_null - Builds an ASN null object.
867 * On entry, datalength is input as the number of valid bytes following
868 * "data". On exit, it is returned as the number of valid bytes
869 * following the beginning of the next object.
871 * Returns a pointer to the first byte past the end
872 * of this object (i.e. the start of the next object).
873 * Returns NULL on any error.
876 asn_build_null(u_char
* data
, int *datalength
, u_char type
)
877 /* u_char *data; IN - pointer to start of object */
878 /* int *datalength; IN/OUT - # of valid bytes left in buf */
879 /* u_char type; IN - ASN type of object */
882 * ASN.1 null ::= 0x05 0x00
884 return (asn_build_header_with_truth(data
, datalength
, type
, 0, 1));
890 * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type.
891 * On entry, datalength is input as the number of valid bytes following
892 * "data". On exit, it is returned as the number of valid bytes
893 * following the beginning of the next object.
895 * "string" is filled with the bit string.
897 * Returns a pointer to the first byte past the end
898 * of this object (i.e. the start of the next object).
899 * Returns NULL on any error.
902 asn_parse_bitstring(u_char
* data
, int *datalength
,
903 u_char
* type
, u_char
* string
, int *strlength
)
904 /* u_char *data; IN - pointer to start of object */
905 /* int *datalength; IN/OUT - # of valid bytes left in buf */
906 /* u_char *type; OUT - asn type of object */
907 /* u_char *string; IN/OUT - pointer to start of output buf */
908 /* int *strlength; IN/OUT - size of output buffer */
911 * bitstring ::= 0x03 asnlength unused {byte}*
917 bufp
= asn_parse_length(bufp
, &asn_length
);
921 if (asn_length
+ (bufp
- data
) > *datalength
) {
922 snmp_set_api_error(SNMPERR_ASN_DECODE
);
925 if (asn_length
> *strlength
) {
926 snmp_set_api_error(SNMPERR_ASN_DECODE
);
929 if (asn_length
< 1) {
930 snmp_set_api_error(SNMPERR_ASN_DECODE
);
933 if ((int) (*(char *) bufp
) < 0 || (int) (*bufp
) > 7) {
934 snmp_set_api_error(SNMPERR_ASN_DECODE
);
937 memcpy((char *) string
, (char *) bufp
, (int) asn_length
);
938 *strlength
= (int) asn_length
;
939 *datalength
-= (int) asn_length
+ (bufp
- data
);
940 return (bufp
+ asn_length
);
944 * asn_build_bitstring - Builds an ASN bit string object containing the
946 * On entry, datalength is input as the number of valid bytes following
947 * "data". On exit, it is returned as the number of valid bytes
948 * following the beginning of the next object.
950 * Returns a pointer to the first byte past the end
951 * of this object (i.e. the start of the next object).
952 * Returns NULL on any error.
955 asn_build_bitstring(u_char
* data
, int *datalength
,
956 u_char type
, u_char
* string
, int strlength
)
957 /* u_char *data; IN - pointer to start of object */
958 /* int *datalength; IN/OUT - # of valid bytes left in buf */
959 /* u_char type; IN - ASN type of string */
960 /* u_char *string; IN - pointer to start of input buffer */
961 /* int strlength; IN - size of input buffer */
964 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
966 if ((strlength
< 1) || ((*(char *) string
) < 0) || ((*string
) > 7)) {
967 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
970 data
= asn_build_header_with_truth(data
, datalength
, type
, strlength
, 1);
974 if (*datalength
< strlength
) {
975 snmp_set_api_error(SNMPERR_ASN_ENCODE
);
978 memcpy((char *) data
, (char *) string
, strlength
);
979 *datalength
-= strlength
;
980 return (data
+ strlength
);
986 * To do: Write an asn_parse_exception function to go with the new
987 * asn_build_exception function below so that the exceptional values can
988 * be handled in input packets aswell as output ones.
992 * asn_build_exception - Builds an ASN exception object.
993 * On entry, datalength is input as the number of valid bytes following
994 * "data". On exit, it is returned as the number of valid bytes
995 * following the beginning of the next object.
997 * Returns a pointer to the first byte past the end
998 * of this object (i.e. the start of the next object).
999 * Returns NULL on any error.
1001 * ASN.1 variable exception ::= 0x8i 0x00, where 'i' is one of these
1002 * exception identifiers:
1004 * 1 -- noSuchInstance
1008 asn_build_exception(u_char
* data
, int *datalength
, u_char type
)
1009 /* u_char *data; IN - pointer to start of object */
1010 /* int *datalength; IN/OUT - # of valid bytes left in buf */
1011 /* u_char type; IN - ASN type of object */
1013 return (asn_build_header_with_truth(data
, datalength
, type
, 0, 1));