]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/snmp.c
4 * SNMP functions for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 2006-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * "LICENSE" which should have been included with this file. If this
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * cupsSNMPClose() - Close a SNMP socket.
20 * cupsSNMPCopyOID() - Copy an OID.
21 * cupsSNMPIsOID() - Test whether a SNMP response contains the
23 * cupsSNMPIsOIDPrefixed() - Test whether a SNMP response uses the specified
25 * cupsSNMPOpen() - Open a SNMP socket.
26 * cupsSNMPRead() - Read and parse a SNMP response...
27 * cupsSNMPSetDebug() - Enable/disable debug logging to stderr.
28 * cupsSNMPWrite() - Send an SNMP query packet.
29 * asn1_decode_snmp() - Decode a SNMP packet.
30 * asn1_debug() - Decode an ASN1-encoded message.
31 * asn1_encode_snmp() - Encode a SNMP packet.
32 * asn1_get_integer() - Get an integer value.
33 * asn1_get_length() - Get a value length.
34 * asn1_get_oid() - Get an OID value.
35 * asn1_get_packed() - Get a packed integer value.
36 * asn1_get_string() - Get a string value.
37 * asn1_get_type() - Get a value type.
38 * asn1_set_integer() - Set an integer value.
39 * asn1_set_length() - Set a value length.
40 * asn1_set_oid() - Set an OID value.
41 * asn1_set_packed() - Set a packed integer value.
42 * asn1_size_integer() - Figure out the number of bytes needed for an
44 * asn1_size_length() - Figure out the number of bytes needed for a
46 * asn1_size_oid() - Figure out the numebr of bytes needed for an OID
48 * asn1_size_packed() - Figure out the number of bytes needed for a
49 * packed integer value.
50 * snmp_set_error() - Set the localized error for a packet.
54 * Include necessary headers.
61 # include <sys/poll.h>
62 #endif /* HAVE_POLL */
69 static int asn1_decode_snmp(unsigned char *buffer
, size_t len
,
71 static void asn1_debug(const char *prefix
, unsigned char *buffer
,
72 size_t len
, int indent
);
73 static int asn1_encode_snmp(unsigned char *buffer
, size_t len
,
75 static int asn1_get_integer(unsigned char **buffer
,
76 unsigned char *bufend
,
78 static int asn1_get_oid(unsigned char **buffer
,
79 unsigned char *bufend
,
80 int length
, int *oid
, int oidsize
);
81 static int asn1_get_packed(unsigned char **buffer
,
82 unsigned char *bufend
);
83 static char *asn1_get_string(unsigned char **buffer
,
84 unsigned char *bufend
,
85 int length
, char *string
,
87 static int asn1_get_length(unsigned char **buffer
,
88 unsigned char *bufend
);
89 static int asn1_get_type(unsigned char **buffer
,
90 unsigned char *bufend
);
91 static void asn1_set_integer(unsigned char **buffer
,
93 static void asn1_set_length(unsigned char **buffer
,
95 static void asn1_set_oid(unsigned char **buffer
,
97 static void asn1_set_packed(unsigned char **buffer
,
99 static int asn1_size_integer(int integer
);
100 static int asn1_size_length(int length
);
101 static int asn1_size_oid(const int *oid
);
102 static int asn1_size_packed(int integer
);
103 static void snmp_set_error(cups_snmp_t
*packet
,
104 const char *message
);
108 * 'cupsSNMPClose()' - Close a SNMP socket.
114 cupsSNMPClose(int fd
) /* I - SNMP socket file descriptor */
125 * 'cupsSNMPCopyOID()' - Copy an OID.
128 int * /* O - New OID */
129 cupsSNMPCopyOID(int *dst
, /* I - Destination OID */
130 const int *src
, /* I - Source OID */
131 int dstsize
) /* I - Number of integers in dst */
133 int i
; /* Looping var */
136 for (i
= 0, dstsize
--; src
[i
] && i
< dstsize
; i
++)
146 * 'cupsSNMPIsOID()' - Test whether a SNMP response contains the specified OID.
148 * The array pointed to by "oid" is 0-terminated.
153 int /* O - 1 if equal, 0 if not equal */
154 cupsSNMPIsOID(cups_snmp_t
*packet
, /* I - Response packet */
155 const int *oid
) /* I - OID */
157 int i
; /* Looping var */
161 * Range check input...
171 for (i
= 0; i
< CUPS_SNMP_MAX_OID
&& oid
[i
] && packet
->object_name
[i
]; i
++)
172 if (oid
[i
] != packet
->object_name
[i
])
175 return (i
< CUPS_SNMP_MAX_OID
&& oid
[i
] == packet
->object_name
[i
]);
180 * 'cupsSNMPIsOIDPrefixed()' - Test whether a SNMP response uses the specified
183 * The array pointed to by "prefix" is 0-terminated.
188 int /* O - 1 if prefixed, 0 if not prefixed */
189 cupsSNMPIsOIDPrefixed(
190 cups_snmp_t
*packet
, /* I - Response packet */
191 const int *prefix
) /* I - OID prefix */
193 int i
; /* Looping var */
197 * Range check input...
200 if (!packet
|| !prefix
)
208 i
< CUPS_SNMP_MAX_OID
&& prefix
[i
] && packet
->object_name
[i
];
210 if (prefix
[i
] != packet
->object_name
[i
])
213 return (i
< CUPS_SNMP_MAX_OID
);
218 * 'cupsSNMPOpen()' - Open a SNMP socket.
223 int /* O - SNMP socket file descriptor */
226 int fd
; /* SNMP socket file descriptor */
227 int val
; /* Socket option value */
231 * Create the SNMP socket...
234 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
238 * Set the "broadcast" flag...
243 if (setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &val
, sizeof(val
)))
255 * 'cupsSNMPRead()' - Read and parse a SNMP response...
257 * If "timeout" is negative, cupsSNMPRead() will wait for a response
263 cups_snmp_t
* /* O - SNMP packet or NULL if none */
264 cupsSNMPRead(int fd
, /* I - SNMP socket file descriptor */
265 cups_snmp_t
*packet
, /* I - SNMP packet buffer */
266 int msec
) /* I - Timeout in milliseconds */
268 unsigned char buffer
[CUPS_SNMP_MAX_PACKET
];
270 int bytes
; /* Number of bytes received */
271 socklen_t addrlen
; /* Source address length */
275 * Range check input...
278 if (fd
< 0 || !packet
)
282 * Optionally wait for a response...
287 int ready
; /* Data ready on socket? */
289 struct pollfd pfd
; /* Polled file descriptor */
294 while ((ready
= poll(&pfd
, 1, msec
)) < 0 && errno
== EINTR
);
297 fd_set input_set
; /* select() input set */
298 struct timeval timeout
; /* select() timeout */
303 FD_SET(fd
, &input_set
);
305 timeout
.tv_sec
= msec
/ 1000;
306 timeout
.tv_usec
= (msec
% 1000) * 1000;
308 ready
= select(fd
+ 1, &input_set
, NULL
, NULL
, &timeout
);
311 while (ready
< 0 && WSAGetLastError() == WSAEINTR
);
313 while (ready
< 0 && errno
== EINTR
);
315 #endif /* HAVE_POLL */
318 * If we don't have any data ready, return right away...
326 * Read the response data...
329 addrlen
= sizeof(packet
->address
);
331 if ((bytes
= recvfrom(fd
, buffer
, sizeof(buffer
), 0,
332 (void *)&(packet
->address
), &addrlen
)) < 0)
336 * Look for the response status code in the SNMP message header...
339 asn1_debug("DEBUG: IN ", buffer
, bytes
, 0);
341 asn1_decode_snmp(buffer
, bytes
, packet
);
344 * Return decoded data packet...
352 * 'cupsSNMPSetDebug()' - Enable/disable debug logging to stderr.
358 cupsSNMPSetDebug(int level
) /* I - 1 to enable debug output, 0 otherwise */
360 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
363 cg
->snmp_debug
= level
;
368 * 'cupsSNMPWrite()' - Send an SNMP query packet.
370 * The array pointed to by "oid" is 0-terminated.
375 int /* O - 1 on success, 0 on error */
377 int fd
, /* I - SNMP socket */
378 http_addr_t
*address
, /* I - Address to send to */
379 int version
, /* I - SNMP version */
380 const char *community
, /* I - Community name */
381 cups_asn1_t request_type
, /* I - Request type */
382 const unsigned request_id
, /* I - Request ID */
383 const int *oid
) /* I - OID */
385 int i
; /* Looping var */
386 cups_snmp_t packet
; /* SNMP message packet */
387 unsigned char buffer
[CUPS_SNMP_MAX_PACKET
];
388 /* SNMP message buffer */
389 int bytes
; /* Size of message */
393 * Create the SNMP message...
396 memset(&packet
, 0, sizeof(packet
));
398 packet
.version
= version
;
399 packet
.request_type
= request_type
;
400 packet
.request_id
= request_id
;
401 packet
.object_type
= CUPS_ASN1_NULL_VALUE
;
403 strlcpy(packet
.community
, community
, sizeof(packet
.community
));
405 for (i
= 0; oid
[i
]; i
++)
406 packet
.object_name
[i
] = oid
[i
];
408 bytes
= asn1_encode_snmp(buffer
, sizeof(buffer
), &packet
);
417 asn1_debug("DEBUG: OUT ", buffer
, bytes
, 0);
420 * Send the message...
424 if (address
->addr
.sa_family
== AF_INET6
)
425 address
->ipv6
.sin6_port
= htons(CUPS_SNMP_PORT
);
427 #endif /* AF_INET6 */
428 address
->ipv4
.sin_port
= htons(CUPS_SNMP_PORT
);
430 return (sendto(fd
, buffer
, bytes
, 0, (void *)address
,
431 httpAddrLength(address
)) == bytes
);
436 * 'asn1_decode_snmp()' - Decode a SNMP packet.
439 static int /* O - 0 on success, -1 on error */
440 asn1_decode_snmp(unsigned char *buffer
, /* I - Buffer */
441 size_t len
, /* I - Size of buffer */
442 cups_snmp_t
*packet
) /* I - SNMP packet */
444 unsigned char *bufptr
, /* Pointer into the data */
445 *bufend
; /* End of data */
446 int length
; /* Length of value */
450 * Initialize the decoding...
453 memset(packet
, 0, sizeof(cups_snmp_t
));
456 bufend
= buffer
+ len
;
458 if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_SEQUENCE
)
459 snmp_set_error(packet
, _("Packet does not start with SEQUENCE"));
460 else if (asn1_get_length(&bufptr
, bufend
) == 0)
461 snmp_set_error(packet
, _("SEQUENCE uses indefinite length"));
462 else if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_INTEGER
)
463 snmp_set_error(packet
, _("No version number"));
464 else if ((length
= asn1_get_length(&bufptr
, bufend
)) == 0)
465 snmp_set_error(packet
, _("Version uses indefinite length"));
466 else if ((packet
->version
= asn1_get_integer(&bufptr
, bufend
, length
))
467 != CUPS_SNMP_VERSION_1
)
468 snmp_set_error(packet
, _("Bad SNMP version number"));
469 else if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_OCTET_STRING
)
470 snmp_set_error(packet
, _("No community name"));
471 else if ((length
= asn1_get_length(&bufptr
, bufend
)) == 0)
472 snmp_set_error(packet
, _("Community name uses indefinite length"));
475 asn1_get_string(&bufptr
, bufend
, length
, packet
->community
,
476 sizeof(packet
->community
));
478 if ((packet
->request_type
= asn1_get_type(&bufptr
, bufend
))
479 != CUPS_ASN1_GET_RESPONSE
)
480 snmp_set_error(packet
, _("Packet does not contain a Get-Response-PDU"));
481 else if (asn1_get_length(&bufptr
, bufend
) == 0)
482 snmp_set_error(packet
, _("Get-Response-PDU uses indefinite length"));
483 else if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_INTEGER
)
484 snmp_set_error(packet
, _("No request-id"));
485 else if ((length
= asn1_get_length(&bufptr
, bufend
)) == 0)
486 snmp_set_error(packet
, _("request-id uses indefinite length"));
489 packet
->request_id
= asn1_get_integer(&bufptr
, bufend
, length
);
491 if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_INTEGER
)
492 snmp_set_error(packet
, _("No error-status"));
493 else if ((length
= asn1_get_length(&bufptr
, bufend
)) == 0)
494 snmp_set_error(packet
, _("error-status uses indefinite length"));
497 packet
->error_status
= asn1_get_integer(&bufptr
, bufend
, length
);
499 if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_INTEGER
)
500 snmp_set_error(packet
, _("No error-index"));
501 else if ((length
= asn1_get_length(&bufptr
, bufend
)) == 0)
502 snmp_set_error(packet
, _("error-index uses indefinite length"));
505 packet
->error_index
= asn1_get_integer(&bufptr
, bufend
, length
);
507 if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_SEQUENCE
)
508 snmp_set_error(packet
, _("No variable-bindings SEQUENCE"));
509 else if (asn1_get_length(&bufptr
, bufend
) == 0)
510 snmp_set_error(packet
,
511 _("variable-bindings uses indefinite length"));
512 else if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_SEQUENCE
)
513 snmp_set_error(packet
, _("No VarBind SEQUENCE"));
514 else if (asn1_get_length(&bufptr
, bufend
) == 0)
515 snmp_set_error(packet
, _("VarBind uses indefinite length"));
516 else if (asn1_get_type(&bufptr
, bufend
) != CUPS_ASN1_OID
)
517 snmp_set_error(packet
, _("No name OID"));
518 else if ((length
= asn1_get_length(&bufptr
, bufend
)) == 0)
519 snmp_set_error(packet
, _("Name OID uses indefinite length"));
522 asn1_get_oid(&bufptr
, bufend
, length
, packet
->object_name
,
525 packet
->object_type
= asn1_get_type(&bufptr
, bufend
);
527 if ((length
= asn1_get_length(&bufptr
, bufend
)) == 0 &&
528 packet
->object_type
!= CUPS_ASN1_NULL_VALUE
&&
529 packet
->object_type
!= CUPS_ASN1_OCTET_STRING
)
530 snmp_set_error(packet
, _("Value uses indefinite length"));
533 switch (packet
->object_type
)
535 case CUPS_ASN1_BOOLEAN
:
536 packet
->object_value
.boolean
=
537 asn1_get_integer(&bufptr
, bufend
, length
);
540 case CUPS_ASN1_INTEGER
:
541 packet
->object_value
.integer
=
542 asn1_get_integer(&bufptr
, bufend
, length
);
545 case CUPS_ASN1_NULL_VALUE
:
548 case CUPS_ASN1_OCTET_STRING
:
549 asn1_get_string(&bufptr
, bufend
, length
,
550 packet
->object_value
.string
,
551 CUPS_SNMP_MAX_STRING
);
555 asn1_get_oid(&bufptr
, bufend
, length
,
556 packet
->object_value
.oid
, CUPS_SNMP_MAX_OID
);
559 case CUPS_ASN1_COUNTER
:
560 packet
->object_value
.counter
=
561 asn1_get_integer(&bufptr
, bufend
, length
);
564 case CUPS_ASN1_GAUGE
:
565 packet
->object_value
.gauge
=
566 asn1_get_integer(&bufptr
, bufend
, length
);
570 snmp_set_error(packet
, _("Unsupported value type"));
580 return (packet
->error
? -1 : 0);
585 * 'asn1_debug()' - Decode an ASN1-encoded message.
589 asn1_debug(const char *prefix
, /* I - Prefix string */
590 unsigned char *buffer
, /* I - Buffer */
591 size_t len
, /* I - Length of buffer */
592 int indent
) /* I - Indentation */
594 int i
; /* Looping var */
595 unsigned char *bufend
; /* End of buffer */
596 int integer
; /* Number value */
597 int oid
[CUPS_SNMP_MAX_OID
]; /* OID value */
598 char string
[CUPS_SNMP_MAX_STRING
];
600 unsigned char value_type
; /* Type of value */
601 int value_length
; /* Length of value */
602 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
605 if (cg
->snmp_debug
<= 0)
608 bufend
= buffer
+ len
;
610 while (buffer
< bufend
)
616 value_type
= asn1_get_type(&buffer
, bufend
);
617 value_length
= asn1_get_length(&buffer
, bufend
);
621 case CUPS_ASN1_BOOLEAN
:
622 integer
= asn1_get_integer(&buffer
, bufend
, value_length
);
624 fprintf(stderr
, "%s%*sBOOLEAN %d bytes %d\n", prefix
, indent
, "",
625 value_length
, integer
);
628 case CUPS_ASN1_INTEGER
:
629 integer
= asn1_get_integer(&buffer
, bufend
, value_length
);
631 fprintf(stderr
, "%s%*sINTEGER %d bytes %d\n", prefix
, indent
, "",
632 value_length
, integer
);
635 case CUPS_ASN1_OCTET_STRING
:
636 fprintf(stderr
, "%s%*sOCTET STRING %d bytes \"%s\"\n", prefix
,
637 indent
, "", value_length
,
638 asn1_get_string(&buffer
, bufend
, value_length
, string
,
642 case CUPS_ASN1_NULL_VALUE
:
643 fprintf(stderr
, "%s%*sNULL VALUE %d bytes\n", prefix
, indent
, "",
646 buffer
+= value_length
;
650 asn1_get_oid(&buffer
, bufend
, value_length
, oid
, CUPS_SNMP_MAX_OID
);
652 fprintf(stderr
, "%s%*sOID %d bytes ", prefix
, indent
, "",
654 for (i
= 0; oid
[i
]; i
++)
655 fprintf(stderr
, ".%d", oid
[i
]);
659 case CUPS_ASN1_SEQUENCE
:
660 fprintf(stderr
, "%s%*sSEQUENCE %d bytes\n", prefix
, indent
, "",
662 asn1_debug(prefix
, buffer
, value_length
, indent
+ 4);
664 buffer
+= value_length
;
667 case CUPS_ASN1_GET_REQUEST
:
668 fprintf(stderr
, "%s%*sGet-Request-PDU %d bytes\n", prefix
, indent
, "",
670 asn1_debug(prefix
, buffer
, value_length
, indent
+ 4);
672 buffer
+= value_length
;
675 case CUPS_ASN1_GET_RESPONSE
:
676 fprintf(stderr
, "%s%*sGet-Response-PDU %d bytes\n", prefix
, indent
,
678 asn1_debug(prefix
, buffer
, value_length
, indent
+ 4);
680 buffer
+= value_length
;
684 fprintf(stderr
, "%s%*sUNKNOWN(%x) %d bytes\n", prefix
, indent
, "",
685 value_type
, value_length
);
687 buffer
+= value_length
;
695 * 'asn1_encode_snmp()' - Encode a SNMP packet.
698 static int /* O - Length on success, -1 on error */
699 asn1_encode_snmp(unsigned char *buffer
, /* I - Buffer */
700 size_t bufsize
, /* I - Size of buffer */
701 cups_snmp_t
*packet
) /* I - SNMP packet */
703 unsigned char *bufptr
; /* Pointer into buffer */
704 int total
, /* Total length */
705 msglen
, /* Length of entire message */
706 commlen
, /* Length of community string */
707 reqlen
, /* Length of request */
708 listlen
, /* Length of variable list */
709 varlen
, /* Length of variable */
710 namelen
, /* Length of object name OID */
711 valuelen
; /* Length of object value */
715 * Get the lengths of the community string, OID, and message...
718 namelen
= asn1_size_oid(packet
->object_name
);
720 switch (packet
->object_type
)
722 case CUPS_ASN1_NULL_VALUE
:
726 case CUPS_ASN1_BOOLEAN
:
727 valuelen
= asn1_size_integer(packet
->object_value
.boolean
);
730 case CUPS_ASN1_INTEGER
:
731 valuelen
= asn1_size_integer(packet
->object_value
.integer
);
734 case CUPS_ASN1_OCTET_STRING
:
735 valuelen
= strlen(packet
->object_value
.string
);
739 valuelen
= asn1_size_oid(packet
->object_value
.oid
);
743 packet
->error
= "Unknown object type";
747 varlen
= 1 + asn1_size_length(namelen
) + namelen
+
748 1 + asn1_size_length(valuelen
) + valuelen
;
749 listlen
= 1 + asn1_size_length(varlen
) + varlen
;
750 reqlen
= 2 + asn1_size_integer(packet
->request_id
) +
751 2 + asn1_size_integer(packet
->error_status
) +
752 2 + asn1_size_integer(packet
->error_index
) +
753 1 + asn1_size_length(listlen
) + listlen
;
754 commlen
= strlen(packet
->community
);
755 msglen
= 2 + asn1_size_integer(packet
->version
) +
756 1 + asn1_size_length(commlen
) + commlen
+
757 1 + asn1_size_length(reqlen
) + reqlen
;
758 total
= 1 + asn1_size_length(msglen
) + msglen
;
762 packet
->error
= "Message too large for buffer";
767 * Then format the message...
772 *bufptr
++ = CUPS_ASN1_SEQUENCE
; /* SNMPv1 message header */
773 asn1_set_length(&bufptr
, msglen
);
775 asn1_set_integer(&bufptr
, packet
->version
);
778 *bufptr
++ = CUPS_ASN1_OCTET_STRING
; /* community */
779 asn1_set_length(&bufptr
, commlen
);
780 memcpy(bufptr
, packet
->community
, commlen
);
783 *bufptr
++ = packet
->request_type
; /* Get-Request-PDU */
784 asn1_set_length(&bufptr
, reqlen
);
786 asn1_set_integer(&bufptr
, packet
->request_id
);
788 asn1_set_integer(&bufptr
, packet
->error_status
);
790 asn1_set_integer(&bufptr
, packet
->error_index
);
792 *bufptr
++ = CUPS_ASN1_SEQUENCE
; /* variable-bindings */
793 asn1_set_length(&bufptr
, listlen
);
795 *bufptr
++ = CUPS_ASN1_SEQUENCE
; /* variable */
796 asn1_set_length(&bufptr
, varlen
);
798 asn1_set_oid(&bufptr
, packet
->object_name
);
801 switch (packet
->object_type
)
803 case CUPS_ASN1_NULL_VALUE
:
804 *bufptr
++ = CUPS_ASN1_NULL_VALUE
;
806 *bufptr
++ = 0; /* Length */
809 case CUPS_ASN1_BOOLEAN
:
810 asn1_set_integer(&bufptr
, packet
->object_value
.boolean
);
813 case CUPS_ASN1_INTEGER
:
814 asn1_set_integer(&bufptr
, packet
->object_value
.integer
);
817 case CUPS_ASN1_OCTET_STRING
:
818 *bufptr
++ = CUPS_ASN1_OCTET_STRING
;
819 asn1_set_length(&bufptr
, valuelen
);
820 memcpy(bufptr
, packet
->object_value
.string
, valuelen
);
825 asn1_set_oid(&bufptr
, packet
->object_value
.oid
);
832 return (bufptr
- buffer
);
837 * 'asn1_get_integer()' - Get an integer value.
840 static int /* O - Integer value */
842 unsigned char **buffer
, /* IO - Pointer in buffer */
843 unsigned char *bufend
, /* I - End of buffer */
844 int length
) /* I - Length of value */
846 int value
; /* Integer value */
850 length
> 0 && *buffer
< bufend
;
851 length
--, (*buffer
) ++)
852 value
= (value
<< 8) | **buffer
;
859 * 'asn1_get_length()' - Get a value length.
862 static int /* O - Length */
863 asn1_get_length(unsigned char **buffer
, /* IO - Pointer in buffer */
864 unsigned char *bufend
) /* I - End of buffer */
866 int length
; /* Length */
873 length
= asn1_get_integer(buffer
, bufend
, length
& 127);
880 * 'asn1_get_oid()' - Get an OID value.
883 static int /* O - Last OID number */
885 unsigned char **buffer
, /* IO - Pointer in buffer */
886 unsigned char *bufend
, /* I - End of buffer */
887 int length
, /* I - Length of value */
888 int *oid
, /* I - OID buffer */
889 int oidsize
) /* I - Size of OID buffer */
891 unsigned char *valend
; /* End of value */
892 int *oidend
; /* End of OID buffer */
893 int number
; /* OID number */
896 valend
= *buffer
+ length
;
897 oidend
= oid
+ oidsize
- 1;
902 number
= asn1_get_packed(buffer
, bufend
);
906 *oid
++ = number
/ 40;
907 number
= number
% 40;
917 while (*buffer
< valend
)
919 number
= asn1_get_packed(buffer
, bufend
);
932 * 'asn1_get_packed()' - Get a packed integer value.
935 static int /* O - Value */
937 unsigned char **buffer
, /* IO - Pointer in buffer */
938 unsigned char *bufend
) /* I - End of buffer */
940 int value
; /* Value */
945 while ((**buffer
& 128) && *buffer
< bufend
)
947 value
= (value
<< 7) | (**buffer
& 127);
951 if (*buffer
< bufend
)
953 value
= (value
<< 7) | **buffer
;
962 * 'asn1_get_string()' - Get a string value.
965 static char * /* O - String */
967 unsigned char **buffer
, /* IO - Pointer in buffer */
968 unsigned char *bufend
, /* I - End of buffer */
969 int length
, /* I - Value length */
970 char *string
, /* I - String buffer */
971 int strsize
) /* I - String buffer size */
976 * Disallow negative lengths!
981 else if (length
< strsize
)
984 * String is smaller than the buffer...
988 memcpy(string
, *buffer
, length
);
990 string
[length
] = '\0';
995 * String is larger than the buffer...
998 memcpy(string
, *buffer
, strsize
- 1);
999 string
[strsize
- 1] = '\0';
1003 (*buffer
) += length
;
1005 return (length
< 0 ? NULL
: string
);
1010 * 'asn1_get_type()' - Get a value type.
1013 static int /* O - Type */
1014 asn1_get_type(unsigned char **buffer
, /* IO - Pointer in buffer */
1015 unsigned char *bufend
) /* I - End of buffer */
1017 int type
; /* Type */
1023 if ((type
& 31) == 31)
1024 type
= asn1_get_packed(buffer
, bufend
);
1031 * 'asn1_set_integer()' - Set an integer value.
1035 asn1_set_integer(unsigned char **buffer
,/* IO - Pointer in buffer */
1036 int integer
) /* I - Integer value */
1038 **buffer
= CUPS_ASN1_INTEGER
;
1041 if (integer
> 0x7fffff || integer
< -0x800000)
1045 **buffer
= integer
>> 24;
1047 **buffer
= integer
>> 16;
1049 **buffer
= integer
>> 8;
1054 else if (integer
> 0x7fff || integer
< -0x8000)
1058 **buffer
= integer
>> 16;
1060 **buffer
= integer
>> 8;
1065 else if (integer
> 0x7f || integer
< -0x80)
1069 **buffer
= integer
>> 8;
1085 * 'asn1_set_length()' - Set a value length.
1089 asn1_set_length(unsigned char **buffer
, /* IO - Pointer in buffer */
1090 int length
) /* I - Length value */
1094 **buffer
= 0x82; /* 2-byte length */
1096 **buffer
= length
>> 8;
1101 else if (length
> 127)
1103 **buffer
= 0x81; /* 1-byte length */
1110 **buffer
= length
; /* Length */
1117 * 'asn1_set_oid()' - Set an OID value.
1121 asn1_set_oid(unsigned char **buffer
, /* IO - Pointer in buffer */
1122 const int *oid
) /* I - OID value */
1124 **buffer
= CUPS_ASN1_OID
;
1127 asn1_set_length(buffer
, asn1_size_oid(oid
));
1129 asn1_set_packed(buffer
, oid
[0] * 40 + oid
[1]);
1131 for (oid
+= 2; *oid
; oid
++)
1132 asn1_set_packed(buffer
, *oid
);
1137 * 'asn1_set_packed()' - Set a packed integer value.
1141 asn1_set_packed(unsigned char **buffer
, /* IO - Pointer in buffer */
1142 int integer
) /* I - Integer value */
1144 if (integer
> 0xfffffff)
1146 **buffer
= (integer
>> 28) & 0x7f;
1150 if (integer
> 0x1fffff)
1152 **buffer
= (integer
>> 21) & 0x7f;
1156 if (integer
> 0x3fff)
1158 **buffer
= (integer
>> 14) & 0x7f;
1164 **buffer
= (integer
>> 7) & 0x7f;
1168 **buffer
= integer
& 0x7f;
1174 * 'asn1_size_integer()' - Figure out the number of bytes needed for an
1178 static int /* O - Size in bytes */
1179 asn1_size_integer(int integer
) /* I - Integer value */
1181 if (integer
> 0x7fffff || integer
< -0x800000)
1183 else if (integer
> 0x7fff || integer
< -0x8000)
1185 else if (integer
> 0x7f || integer
< -0x80)
1193 * 'asn1_size_length()' - Figure out the number of bytes needed for a
1197 static int /* O - Size in bytes */
1198 asn1_size_length(int length
) /* I - Length value */
1202 else if (length
> 0x7f)
1210 * 'asn1_size_oid()' - Figure out the numebr of bytes needed for an
1214 static int /* O - Size in bytes */
1215 asn1_size_oid(const int *oid
) /* I - OID value */
1217 int length
; /* Length of value */
1220 for (length
= asn1_size_packed(oid
[0] * 40 + oid
[1]), oid
+= 2; *oid
; oid
++)
1221 length
+= asn1_size_packed(*oid
);
1228 * 'asn1_size_packed()' - Figure out the number of bytes needed for a
1229 * packed integer value.
1232 static int /* O - Size in bytes */
1233 asn1_size_packed(int integer
) /* I - Integer value */
1235 if (integer
> 0xfffffff)
1237 else if (integer
> 0x1fffff)
1239 else if (integer
> 0x3fff)
1241 else if (integer
> 0x7f)
1249 * 'snmp_set_error()' - Set the localized error for a packet.
1253 snmp_set_error(cups_snmp_t
*packet
, /* I - Packet */
1254 const char *message
) /* I - Error message */
1256 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
1259 if (!cg
->lang_default
)
1260 cg
->lang_default
= cupsLangDefault();
1262 packet
->error
= _cupsLangString(cg
->lang_default
, message
);