1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * SNMP functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2006-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker */
10*5e7646d2SAndroid Build Coastguard Worker
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
13*5e7646d2SAndroid Build Coastguard Worker */
14*5e7646d2SAndroid Build Coastguard Worker
15*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include "snmp-private.h"
17*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
18*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_POLL
19*5e7646d2SAndroid Build Coastguard Worker # include <poll.h>
20*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_POLL */
21*5e7646d2SAndroid Build Coastguard Worker
22*5e7646d2SAndroid Build Coastguard Worker
23*5e7646d2SAndroid Build Coastguard Worker /*
24*5e7646d2SAndroid Build Coastguard Worker * Local functions...
25*5e7646d2SAndroid Build Coastguard Worker */
26*5e7646d2SAndroid Build Coastguard Worker
27*5e7646d2SAndroid Build Coastguard Worker static void asn1_debug(const char *prefix, unsigned char *buffer,
28*5e7646d2SAndroid Build Coastguard Worker size_t len, int indent);
29*5e7646d2SAndroid Build Coastguard Worker static int asn1_decode_snmp(unsigned char *buffer, size_t len,
30*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t *packet);
31*5e7646d2SAndroid Build Coastguard Worker static int asn1_encode_snmp(unsigned char *buffer, size_t len,
32*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t *packet);
33*5e7646d2SAndroid Build Coastguard Worker static int asn1_get_integer(unsigned char **buffer,
34*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend,
35*5e7646d2SAndroid Build Coastguard Worker unsigned length);
36*5e7646d2SAndroid Build Coastguard Worker static int asn1_get_oid(unsigned char **buffer,
37*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend,
38*5e7646d2SAndroid Build Coastguard Worker unsigned length, int *oid, int oidsize);
39*5e7646d2SAndroid Build Coastguard Worker static int asn1_get_packed(unsigned char **buffer,
40*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend);
41*5e7646d2SAndroid Build Coastguard Worker static char *asn1_get_string(unsigned char **buffer,
42*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend,
43*5e7646d2SAndroid Build Coastguard Worker unsigned length, char *string,
44*5e7646d2SAndroid Build Coastguard Worker size_t strsize);
45*5e7646d2SAndroid Build Coastguard Worker static unsigned asn1_get_length(unsigned char **buffer,
46*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend);
47*5e7646d2SAndroid Build Coastguard Worker static int asn1_get_type(unsigned char **buffer,
48*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend);
49*5e7646d2SAndroid Build Coastguard Worker static void asn1_set_integer(unsigned char **buffer,
50*5e7646d2SAndroid Build Coastguard Worker int integer);
51*5e7646d2SAndroid Build Coastguard Worker static void asn1_set_length(unsigned char **buffer,
52*5e7646d2SAndroid Build Coastguard Worker unsigned length);
53*5e7646d2SAndroid Build Coastguard Worker static void asn1_set_oid(unsigned char **buffer,
54*5e7646d2SAndroid Build Coastguard Worker const int *oid);
55*5e7646d2SAndroid Build Coastguard Worker static void asn1_set_packed(unsigned char **buffer,
56*5e7646d2SAndroid Build Coastguard Worker int integer);
57*5e7646d2SAndroid Build Coastguard Worker static unsigned asn1_size_integer(int integer);
58*5e7646d2SAndroid Build Coastguard Worker static unsigned asn1_size_length(unsigned length);
59*5e7646d2SAndroid Build Coastguard Worker static unsigned asn1_size_oid(const int *oid);
60*5e7646d2SAndroid Build Coastguard Worker static unsigned asn1_size_packed(int integer);
61*5e7646d2SAndroid Build Coastguard Worker static void snmp_set_error(cups_snmp_t *packet,
62*5e7646d2SAndroid Build Coastguard Worker const char *message);
63*5e7646d2SAndroid Build Coastguard Worker
64*5e7646d2SAndroid Build Coastguard Worker
65*5e7646d2SAndroid Build Coastguard Worker /*
66*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPClose()' - Close a SNMP socket.
67*5e7646d2SAndroid Build Coastguard Worker */
68*5e7646d2SAndroid Build Coastguard Worker
69*5e7646d2SAndroid Build Coastguard Worker void
_cupsSNMPClose(int fd)70*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPClose(int fd) /* I - SNMP socket file descriptor */
71*5e7646d2SAndroid Build Coastguard Worker {
72*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPClose(fd=%d)", fd));
73*5e7646d2SAndroid Build Coastguard Worker
74*5e7646d2SAndroid Build Coastguard Worker httpAddrClose(NULL, fd);
75*5e7646d2SAndroid Build Coastguard Worker }
76*5e7646d2SAndroid Build Coastguard Worker
77*5e7646d2SAndroid Build Coastguard Worker
78*5e7646d2SAndroid Build Coastguard Worker /*
79*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPCopyOID()' - Copy an OID.
80*5e7646d2SAndroid Build Coastguard Worker *
81*5e7646d2SAndroid Build Coastguard Worker * The array pointed to by "src" is terminated by the value -1.
82*5e7646d2SAndroid Build Coastguard Worker */
83*5e7646d2SAndroid Build Coastguard Worker
84*5e7646d2SAndroid Build Coastguard Worker int * /* O - New OID */
_cupsSNMPCopyOID(int * dst,const int * src,int dstsize)85*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPCopyOID(int *dst, /* I - Destination OID */
86*5e7646d2SAndroid Build Coastguard Worker const int *src, /* I - Source OID */
87*5e7646d2SAndroid Build Coastguard Worker int dstsize) /* I - Number of integers in dst */
88*5e7646d2SAndroid Build Coastguard Worker {
89*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
90*5e7646d2SAndroid Build Coastguard Worker
91*5e7646d2SAndroid Build Coastguard Worker
92*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPCopyOID(dst=%p, src=%p, dstsize=%d)", dst, src,
93*5e7646d2SAndroid Build Coastguard Worker dstsize));
94*5e7646d2SAndroid Build Coastguard Worker
95*5e7646d2SAndroid Build Coastguard Worker for (i = 0, dstsize --; src[i] >= 0 && i < dstsize; i ++)
96*5e7646d2SAndroid Build Coastguard Worker dst[i] = src[i];
97*5e7646d2SAndroid Build Coastguard Worker
98*5e7646d2SAndroid Build Coastguard Worker dst[i] = -1;
99*5e7646d2SAndroid Build Coastguard Worker
100*5e7646d2SAndroid Build Coastguard Worker return (dst);
101*5e7646d2SAndroid Build Coastguard Worker }
102*5e7646d2SAndroid Build Coastguard Worker
103*5e7646d2SAndroid Build Coastguard Worker
104*5e7646d2SAndroid Build Coastguard Worker /*
105*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPDefaultCommunity()' - Get the default SNMP community name.
106*5e7646d2SAndroid Build Coastguard Worker *
107*5e7646d2SAndroid Build Coastguard Worker * The default community name is the first community name found in the
108*5e7646d2SAndroid Build Coastguard Worker * snmp.conf file. If no community name is defined there, "public" is used.
109*5e7646d2SAndroid Build Coastguard Worker */
110*5e7646d2SAndroid Build Coastguard Worker
111*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Default community name */
_cupsSNMPDefaultCommunity(void)112*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPDefaultCommunity(void)
113*5e7646d2SAndroid Build Coastguard Worker {
114*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* snmp.conf file */
115*5e7646d2SAndroid Build Coastguard Worker char line[1024], /* Line from file */
116*5e7646d2SAndroid Build Coastguard Worker *value; /* Value from file */
117*5e7646d2SAndroid Build Coastguard Worker int linenum; /* Line number in file */
118*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals(); /* Global data */
119*5e7646d2SAndroid Build Coastguard Worker
120*5e7646d2SAndroid Build Coastguard Worker
121*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("4_cupsSNMPDefaultCommunity()");
122*5e7646d2SAndroid Build Coastguard Worker
123*5e7646d2SAndroid Build Coastguard Worker if (!cg->snmp_community[0])
124*5e7646d2SAndroid Build Coastguard Worker {
125*5e7646d2SAndroid Build Coastguard Worker strlcpy(cg->snmp_community, "public", sizeof(cg->snmp_community));
126*5e7646d2SAndroid Build Coastguard Worker
127*5e7646d2SAndroid Build Coastguard Worker snprintf(line, sizeof(line), "%s/snmp.conf", cg->cups_serverroot);
128*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(line, "r")) != NULL)
129*5e7646d2SAndroid Build Coastguard Worker {
130*5e7646d2SAndroid Build Coastguard Worker linenum = 0;
131*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
132*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(line, "Community"))
133*5e7646d2SAndroid Build Coastguard Worker {
134*5e7646d2SAndroid Build Coastguard Worker if (value)
135*5e7646d2SAndroid Build Coastguard Worker strlcpy(cg->snmp_community, value, sizeof(cg->snmp_community));
136*5e7646d2SAndroid Build Coastguard Worker else
137*5e7646d2SAndroid Build Coastguard Worker cg->snmp_community[0] = '\0';
138*5e7646d2SAndroid Build Coastguard Worker
139*5e7646d2SAndroid Build Coastguard Worker break;
140*5e7646d2SAndroid Build Coastguard Worker }
141*5e7646d2SAndroid Build Coastguard Worker
142*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
143*5e7646d2SAndroid Build Coastguard Worker }
144*5e7646d2SAndroid Build Coastguard Worker }
145*5e7646d2SAndroid Build Coastguard Worker
146*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPDefaultCommunity: Returning \"%s\"",
147*5e7646d2SAndroid Build Coastguard Worker cg->snmp_community));
148*5e7646d2SAndroid Build Coastguard Worker
149*5e7646d2SAndroid Build Coastguard Worker return (cg->snmp_community);
150*5e7646d2SAndroid Build Coastguard Worker }
151*5e7646d2SAndroid Build Coastguard Worker
152*5e7646d2SAndroid Build Coastguard Worker
153*5e7646d2SAndroid Build Coastguard Worker /*
154*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPIsOID()' - Test whether a SNMP response contains the specified OID.
155*5e7646d2SAndroid Build Coastguard Worker *
156*5e7646d2SAndroid Build Coastguard Worker * The array pointed to by "oid" is terminated by the value -1.
157*5e7646d2SAndroid Build Coastguard Worker */
158*5e7646d2SAndroid Build Coastguard Worker
159*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 if equal, 0 if not equal */
_cupsSNMPIsOID(cups_snmp_t * packet,const int * oid)160*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPIsOID(cups_snmp_t *packet, /* I - Response packet */
161*5e7646d2SAndroid Build Coastguard Worker const int *oid) /* I - OID */
162*5e7646d2SAndroid Build Coastguard Worker {
163*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
164*5e7646d2SAndroid Build Coastguard Worker
165*5e7646d2SAndroid Build Coastguard Worker
166*5e7646d2SAndroid Build Coastguard Worker /*
167*5e7646d2SAndroid Build Coastguard Worker * Range check input...
168*5e7646d2SAndroid Build Coastguard Worker */
169*5e7646d2SAndroid Build Coastguard Worker
170*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPIsOID(packet=%p, oid=%p)", packet, oid));
171*5e7646d2SAndroid Build Coastguard Worker
172*5e7646d2SAndroid Build Coastguard Worker if (!packet || !oid)
173*5e7646d2SAndroid Build Coastguard Worker {
174*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPIsOID: Returning 0");
175*5e7646d2SAndroid Build Coastguard Worker
176*5e7646d2SAndroid Build Coastguard Worker return (0);
177*5e7646d2SAndroid Build Coastguard Worker }
178*5e7646d2SAndroid Build Coastguard Worker
179*5e7646d2SAndroid Build Coastguard Worker /*
180*5e7646d2SAndroid Build Coastguard Worker * Compare OIDs...
181*5e7646d2SAndroid Build Coastguard Worker */
182*5e7646d2SAndroid Build Coastguard Worker
183*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
184*5e7646d2SAndroid Build Coastguard Worker i < CUPS_SNMP_MAX_OID && oid[i] >= 0 && packet->object_name[i] >= 0;
185*5e7646d2SAndroid Build Coastguard Worker i ++)
186*5e7646d2SAndroid Build Coastguard Worker if (oid[i] != packet->object_name[i])
187*5e7646d2SAndroid Build Coastguard Worker {
188*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPIsOID: Returning 0");
189*5e7646d2SAndroid Build Coastguard Worker
190*5e7646d2SAndroid Build Coastguard Worker return (0);
191*5e7646d2SAndroid Build Coastguard Worker }
192*5e7646d2SAndroid Build Coastguard Worker
193*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPIsOID: Returning %d",
194*5e7646d2SAndroid Build Coastguard Worker i < CUPS_SNMP_MAX_OID && oid[i] == packet->object_name[i]));
195*5e7646d2SAndroid Build Coastguard Worker
196*5e7646d2SAndroid Build Coastguard Worker return (i < CUPS_SNMP_MAX_OID && oid[i] == packet->object_name[i]);
197*5e7646d2SAndroid Build Coastguard Worker }
198*5e7646d2SAndroid Build Coastguard Worker
199*5e7646d2SAndroid Build Coastguard Worker
200*5e7646d2SAndroid Build Coastguard Worker /*
201*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPIsOIDPrefixed()' - Test whether a SNMP response uses the specified
202*5e7646d2SAndroid Build Coastguard Worker * OID prefix.
203*5e7646d2SAndroid Build Coastguard Worker *
204*5e7646d2SAndroid Build Coastguard Worker * The array pointed to by "prefix" is terminated by the value -1.
205*5e7646d2SAndroid Build Coastguard Worker */
206*5e7646d2SAndroid Build Coastguard Worker
207*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 if prefixed, 0 if not prefixed */
_cupsSNMPIsOIDPrefixed(cups_snmp_t * packet,const int * prefix)208*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPIsOIDPrefixed(
209*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t *packet, /* I - Response packet */
210*5e7646d2SAndroid Build Coastguard Worker const int *prefix) /* I - OID prefix */
211*5e7646d2SAndroid Build Coastguard Worker {
212*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
213*5e7646d2SAndroid Build Coastguard Worker
214*5e7646d2SAndroid Build Coastguard Worker
215*5e7646d2SAndroid Build Coastguard Worker /*
216*5e7646d2SAndroid Build Coastguard Worker * Range check input...
217*5e7646d2SAndroid Build Coastguard Worker */
218*5e7646d2SAndroid Build Coastguard Worker
219*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPIsOIDPrefixed(packet=%p, prefix=%p)", packet,
220*5e7646d2SAndroid Build Coastguard Worker prefix));
221*5e7646d2SAndroid Build Coastguard Worker
222*5e7646d2SAndroid Build Coastguard Worker if (!packet || !prefix)
223*5e7646d2SAndroid Build Coastguard Worker {
224*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPIsOIDPrefixed: Returning 0");
225*5e7646d2SAndroid Build Coastguard Worker
226*5e7646d2SAndroid Build Coastguard Worker return (0);
227*5e7646d2SAndroid Build Coastguard Worker }
228*5e7646d2SAndroid Build Coastguard Worker
229*5e7646d2SAndroid Build Coastguard Worker /*
230*5e7646d2SAndroid Build Coastguard Worker * Compare OIDs...
231*5e7646d2SAndroid Build Coastguard Worker */
232*5e7646d2SAndroid Build Coastguard Worker
233*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
234*5e7646d2SAndroid Build Coastguard Worker i < CUPS_SNMP_MAX_OID && prefix[i] >= 0 && packet->object_name[i] >= 0;
235*5e7646d2SAndroid Build Coastguard Worker i ++)
236*5e7646d2SAndroid Build Coastguard Worker if (prefix[i] != packet->object_name[i])
237*5e7646d2SAndroid Build Coastguard Worker {
238*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPIsOIDPrefixed: Returning 0");
239*5e7646d2SAndroid Build Coastguard Worker
240*5e7646d2SAndroid Build Coastguard Worker return (0);
241*5e7646d2SAndroid Build Coastguard Worker }
242*5e7646d2SAndroid Build Coastguard Worker
243*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPIsOIDPrefixed: Returning %d",
244*5e7646d2SAndroid Build Coastguard Worker i < CUPS_SNMP_MAX_OID));
245*5e7646d2SAndroid Build Coastguard Worker
246*5e7646d2SAndroid Build Coastguard Worker return (i < CUPS_SNMP_MAX_OID);
247*5e7646d2SAndroid Build Coastguard Worker }
248*5e7646d2SAndroid Build Coastguard Worker
249*5e7646d2SAndroid Build Coastguard Worker
250*5e7646d2SAndroid Build Coastguard Worker /*
251*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPOIDToString()' - Convert an OID to a string.
252*5e7646d2SAndroid Build Coastguard Worker */
253*5e7646d2SAndroid Build Coastguard Worker
254*5e7646d2SAndroid Build Coastguard Worker
255*5e7646d2SAndroid Build Coastguard Worker char * /* O - New string or @code NULL@ on error */
_cupsSNMPOIDToString(const int * src,char * dst,size_t dstsize)256*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPOIDToString(const int *src, /* I - OID */
257*5e7646d2SAndroid Build Coastguard Worker char *dst, /* I - String buffer */
258*5e7646d2SAndroid Build Coastguard Worker size_t dstsize) /* I - Size of string buffer */
259*5e7646d2SAndroid Build Coastguard Worker {
260*5e7646d2SAndroid Build Coastguard Worker char *dstptr, /* Pointer into string buffer */
261*5e7646d2SAndroid Build Coastguard Worker *dstend; /* End of string buffer */
262*5e7646d2SAndroid Build Coastguard Worker
263*5e7646d2SAndroid Build Coastguard Worker
264*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPOIDToString(src=%p, dst=%p, dstsize=" CUPS_LLFMT ")",
265*5e7646d2SAndroid Build Coastguard Worker src, dst, CUPS_LLCAST dstsize));
266*5e7646d2SAndroid Build Coastguard Worker
267*5e7646d2SAndroid Build Coastguard Worker /*
268*5e7646d2SAndroid Build Coastguard Worker * Range check input...
269*5e7646d2SAndroid Build Coastguard Worker */
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker if (!src || !dst || dstsize < 4)
272*5e7646d2SAndroid Build Coastguard Worker return (NULL);
273*5e7646d2SAndroid Build Coastguard Worker
274*5e7646d2SAndroid Build Coastguard Worker /*
275*5e7646d2SAndroid Build Coastguard Worker * Loop through the OID array and build a string...
276*5e7646d2SAndroid Build Coastguard Worker */
277*5e7646d2SAndroid Build Coastguard Worker
278*5e7646d2SAndroid Build Coastguard Worker for (dstptr = dst, dstend = dstptr + dstsize - 1;
279*5e7646d2SAndroid Build Coastguard Worker *src >= 0 && dstptr < dstend;
280*5e7646d2SAndroid Build Coastguard Worker src ++, dstptr += strlen(dstptr))
281*5e7646d2SAndroid Build Coastguard Worker snprintf(dstptr, (size_t)(dstend - dstptr + 1), ".%d", *src);
282*5e7646d2SAndroid Build Coastguard Worker
283*5e7646d2SAndroid Build Coastguard Worker if (*src >= 0)
284*5e7646d2SAndroid Build Coastguard Worker return (NULL);
285*5e7646d2SAndroid Build Coastguard Worker else
286*5e7646d2SAndroid Build Coastguard Worker return (dst);
287*5e7646d2SAndroid Build Coastguard Worker }
288*5e7646d2SAndroid Build Coastguard Worker
289*5e7646d2SAndroid Build Coastguard Worker
290*5e7646d2SAndroid Build Coastguard Worker /*
291*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPOpen()' - Open a SNMP socket.
292*5e7646d2SAndroid Build Coastguard Worker */
293*5e7646d2SAndroid Build Coastguard Worker
294*5e7646d2SAndroid Build Coastguard Worker int /* O - SNMP socket file descriptor */
_cupsSNMPOpen(int family)295*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPOpen(int family) /* I - Address family - @code AF_INET@ or @code AF_INET6@ */
296*5e7646d2SAndroid Build Coastguard Worker {
297*5e7646d2SAndroid Build Coastguard Worker int fd; /* SNMP socket file descriptor */
298*5e7646d2SAndroid Build Coastguard Worker int val; /* Socket option value */
299*5e7646d2SAndroid Build Coastguard Worker
300*5e7646d2SAndroid Build Coastguard Worker
301*5e7646d2SAndroid Build Coastguard Worker /*
302*5e7646d2SAndroid Build Coastguard Worker * Create the SNMP socket...
303*5e7646d2SAndroid Build Coastguard Worker */
304*5e7646d2SAndroid Build Coastguard Worker
305*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPOpen(family=%d)", family));
306*5e7646d2SAndroid Build Coastguard Worker
307*5e7646d2SAndroid Build Coastguard Worker if ((fd = socket(family, SOCK_DGRAM, 0)) < 0)
308*5e7646d2SAndroid Build Coastguard Worker {
309*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPOpen: Returning -1 (%s)", strerror(errno)));
310*5e7646d2SAndroid Build Coastguard Worker
311*5e7646d2SAndroid Build Coastguard Worker return (-1);
312*5e7646d2SAndroid Build Coastguard Worker }
313*5e7646d2SAndroid Build Coastguard Worker
314*5e7646d2SAndroid Build Coastguard Worker /*
315*5e7646d2SAndroid Build Coastguard Worker * Set the "broadcast" flag...
316*5e7646d2SAndroid Build Coastguard Worker */
317*5e7646d2SAndroid Build Coastguard Worker
318*5e7646d2SAndroid Build Coastguard Worker val = 1;
319*5e7646d2SAndroid Build Coastguard Worker
320*5e7646d2SAndroid Build Coastguard Worker if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, CUPS_SOCAST &val, sizeof(val)))
321*5e7646d2SAndroid Build Coastguard Worker {
322*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPOpen: Returning -1 (%s)", strerror(errno)));
323*5e7646d2SAndroid Build Coastguard Worker
324*5e7646d2SAndroid Build Coastguard Worker close(fd);
325*5e7646d2SAndroid Build Coastguard Worker
326*5e7646d2SAndroid Build Coastguard Worker return (-1);
327*5e7646d2SAndroid Build Coastguard Worker }
328*5e7646d2SAndroid Build Coastguard Worker
329*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPOpen: Returning %d", fd));
330*5e7646d2SAndroid Build Coastguard Worker
331*5e7646d2SAndroid Build Coastguard Worker return (fd);
332*5e7646d2SAndroid Build Coastguard Worker }
333*5e7646d2SAndroid Build Coastguard Worker
334*5e7646d2SAndroid Build Coastguard Worker
335*5e7646d2SAndroid Build Coastguard Worker /*
336*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPRead()' - Read and parse a SNMP response.
337*5e7646d2SAndroid Build Coastguard Worker *
338*5e7646d2SAndroid Build Coastguard Worker * If "timeout" is negative, @code _cupsSNMPRead@ will wait for a response
339*5e7646d2SAndroid Build Coastguard Worker * indefinitely.
340*5e7646d2SAndroid Build Coastguard Worker */
341*5e7646d2SAndroid Build Coastguard Worker
342*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t * /* O - SNMP packet or @code NULL@ if none */
_cupsSNMPRead(int fd,cups_snmp_t * packet,double timeout)343*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPRead(int fd, /* I - SNMP socket file descriptor */
344*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t *packet, /* I - SNMP packet buffer */
345*5e7646d2SAndroid Build Coastguard Worker double timeout) /* I - Timeout in seconds */
346*5e7646d2SAndroid Build Coastguard Worker {
347*5e7646d2SAndroid Build Coastguard Worker unsigned char buffer[CUPS_SNMP_MAX_PACKET];
348*5e7646d2SAndroid Build Coastguard Worker /* Data packet */
349*5e7646d2SAndroid Build Coastguard Worker ssize_t bytes; /* Number of bytes received */
350*5e7646d2SAndroid Build Coastguard Worker socklen_t addrlen; /* Source address length */
351*5e7646d2SAndroid Build Coastguard Worker http_addr_t address; /* Source address */
352*5e7646d2SAndroid Build Coastguard Worker
353*5e7646d2SAndroid Build Coastguard Worker
354*5e7646d2SAndroid Build Coastguard Worker /*
355*5e7646d2SAndroid Build Coastguard Worker * Range check input...
356*5e7646d2SAndroid Build Coastguard Worker */
357*5e7646d2SAndroid Build Coastguard Worker
358*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPRead(fd=%d, packet=%p, timeout=%.1f)", fd, packet,
359*5e7646d2SAndroid Build Coastguard Worker timeout));
360*5e7646d2SAndroid Build Coastguard Worker
361*5e7646d2SAndroid Build Coastguard Worker if (fd < 0 || !packet)
362*5e7646d2SAndroid Build Coastguard Worker {
363*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPRead: Returning NULL");
364*5e7646d2SAndroid Build Coastguard Worker
365*5e7646d2SAndroid Build Coastguard Worker return (NULL);
366*5e7646d2SAndroid Build Coastguard Worker }
367*5e7646d2SAndroid Build Coastguard Worker
368*5e7646d2SAndroid Build Coastguard Worker /*
369*5e7646d2SAndroid Build Coastguard Worker * Optionally wait for a response...
370*5e7646d2SAndroid Build Coastguard Worker */
371*5e7646d2SAndroid Build Coastguard Worker
372*5e7646d2SAndroid Build Coastguard Worker if (timeout >= 0.0)
373*5e7646d2SAndroid Build Coastguard Worker {
374*5e7646d2SAndroid Build Coastguard Worker int ready; /* Data ready on socket? */
375*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_POLL
376*5e7646d2SAndroid Build Coastguard Worker struct pollfd pfd; /* Polled file descriptor */
377*5e7646d2SAndroid Build Coastguard Worker
378*5e7646d2SAndroid Build Coastguard Worker pfd.fd = fd;
379*5e7646d2SAndroid Build Coastguard Worker pfd.events = POLLIN;
380*5e7646d2SAndroid Build Coastguard Worker
381*5e7646d2SAndroid Build Coastguard Worker while ((ready = poll(&pfd, 1, (int)(timeout * 1000.0))) < 0 &&
382*5e7646d2SAndroid Build Coastguard Worker (errno == EINTR || errno == EAGAIN));
383*5e7646d2SAndroid Build Coastguard Worker
384*5e7646d2SAndroid Build Coastguard Worker #else
385*5e7646d2SAndroid Build Coastguard Worker fd_set input_set; /* select() input set */
386*5e7646d2SAndroid Build Coastguard Worker struct timeval stimeout; /* select() timeout */
387*5e7646d2SAndroid Build Coastguard Worker
388*5e7646d2SAndroid Build Coastguard Worker do
389*5e7646d2SAndroid Build Coastguard Worker {
390*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&input_set);
391*5e7646d2SAndroid Build Coastguard Worker FD_SET(fd, &input_set);
392*5e7646d2SAndroid Build Coastguard Worker
393*5e7646d2SAndroid Build Coastguard Worker stimeout.tv_sec = (int)timeout;
394*5e7646d2SAndroid Build Coastguard Worker stimeout.tv_usec = (int)((timeout - stimeout.tv_sec) * 1000000);
395*5e7646d2SAndroid Build Coastguard Worker
396*5e7646d2SAndroid Build Coastguard Worker ready = select(fd + 1, &input_set, NULL, NULL, &stimeout);
397*5e7646d2SAndroid Build Coastguard Worker }
398*5e7646d2SAndroid Build Coastguard Worker # ifdef _WIN32
399*5e7646d2SAndroid Build Coastguard Worker while (ready < 0 && WSAGetLastError() == WSAEINTR);
400*5e7646d2SAndroid Build Coastguard Worker # else
401*5e7646d2SAndroid Build Coastguard Worker while (ready < 0 && (errno == EINTR || errno == EAGAIN));
402*5e7646d2SAndroid Build Coastguard Worker # endif /* _WIN32 */
403*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_POLL */
404*5e7646d2SAndroid Build Coastguard Worker
405*5e7646d2SAndroid Build Coastguard Worker /*
406*5e7646d2SAndroid Build Coastguard Worker * If we don't have any data ready, return right away...
407*5e7646d2SAndroid Build Coastguard Worker */
408*5e7646d2SAndroid Build Coastguard Worker
409*5e7646d2SAndroid Build Coastguard Worker if (ready <= 0)
410*5e7646d2SAndroid Build Coastguard Worker {
411*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPRead: Returning NULL (timeout)");
412*5e7646d2SAndroid Build Coastguard Worker
413*5e7646d2SAndroid Build Coastguard Worker return (NULL);
414*5e7646d2SAndroid Build Coastguard Worker }
415*5e7646d2SAndroid Build Coastguard Worker }
416*5e7646d2SAndroid Build Coastguard Worker
417*5e7646d2SAndroid Build Coastguard Worker /*
418*5e7646d2SAndroid Build Coastguard Worker * Read the response data...
419*5e7646d2SAndroid Build Coastguard Worker */
420*5e7646d2SAndroid Build Coastguard Worker
421*5e7646d2SAndroid Build Coastguard Worker addrlen = sizeof(address);
422*5e7646d2SAndroid Build Coastguard Worker
423*5e7646d2SAndroid Build Coastguard Worker if ((bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (void *)&address,
424*5e7646d2SAndroid Build Coastguard Worker &addrlen)) < 0)
425*5e7646d2SAndroid Build Coastguard Worker {
426*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPRead: Returning NULL (%s)", strerror(errno)));
427*5e7646d2SAndroid Build Coastguard Worker
428*5e7646d2SAndroid Build Coastguard Worker return (NULL);
429*5e7646d2SAndroid Build Coastguard Worker }
430*5e7646d2SAndroid Build Coastguard Worker
431*5e7646d2SAndroid Build Coastguard Worker /*
432*5e7646d2SAndroid Build Coastguard Worker * Look for the response status code in the SNMP message header...
433*5e7646d2SAndroid Build Coastguard Worker */
434*5e7646d2SAndroid Build Coastguard Worker
435*5e7646d2SAndroid Build Coastguard Worker asn1_debug("DEBUG: IN ", buffer, (size_t)bytes, 0);
436*5e7646d2SAndroid Build Coastguard Worker
437*5e7646d2SAndroid Build Coastguard Worker asn1_decode_snmp(buffer, (size_t)bytes, packet);
438*5e7646d2SAndroid Build Coastguard Worker
439*5e7646d2SAndroid Build Coastguard Worker memcpy(&(packet->address), &address, sizeof(packet->address));
440*5e7646d2SAndroid Build Coastguard Worker
441*5e7646d2SAndroid Build Coastguard Worker /*
442*5e7646d2SAndroid Build Coastguard Worker * Return decoded data packet...
443*5e7646d2SAndroid Build Coastguard Worker */
444*5e7646d2SAndroid Build Coastguard Worker
445*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPRead: Returning packet");
446*5e7646d2SAndroid Build Coastguard Worker
447*5e7646d2SAndroid Build Coastguard Worker return (packet);
448*5e7646d2SAndroid Build Coastguard Worker }
449*5e7646d2SAndroid Build Coastguard Worker
450*5e7646d2SAndroid Build Coastguard Worker
451*5e7646d2SAndroid Build Coastguard Worker /*
452*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPSetDebug()' - Enable/disable debug logging to stderr.
453*5e7646d2SAndroid Build Coastguard Worker */
454*5e7646d2SAndroid Build Coastguard Worker
455*5e7646d2SAndroid Build Coastguard Worker void
_cupsSNMPSetDebug(int level)456*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPSetDebug(int level) /* I - 1 to enable debug output, 0 otherwise */
457*5e7646d2SAndroid Build Coastguard Worker {
458*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals(); /* Global data */
459*5e7646d2SAndroid Build Coastguard Worker
460*5e7646d2SAndroid Build Coastguard Worker
461*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPSetDebug(level=%d)", level));
462*5e7646d2SAndroid Build Coastguard Worker
463*5e7646d2SAndroid Build Coastguard Worker cg->snmp_debug = level;
464*5e7646d2SAndroid Build Coastguard Worker }
465*5e7646d2SAndroid Build Coastguard Worker
466*5e7646d2SAndroid Build Coastguard Worker
467*5e7646d2SAndroid Build Coastguard Worker /*
468*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPStringToOID()' - Convert a numeric OID string to an OID array.
469*5e7646d2SAndroid Build Coastguard Worker *
470*5e7646d2SAndroid Build Coastguard Worker * This function converts a string of the form ".N.N.N.N.N" to the
471*5e7646d2SAndroid Build Coastguard Worker * corresponding OID array terminated by -1.
472*5e7646d2SAndroid Build Coastguard Worker *
473*5e7646d2SAndroid Build Coastguard Worker * @code NULL@ is returned if the array is not large enough or the string is
474*5e7646d2SAndroid Build Coastguard Worker * not a valid OID number.
475*5e7646d2SAndroid Build Coastguard Worker */
476*5e7646d2SAndroid Build Coastguard Worker
477*5e7646d2SAndroid Build Coastguard Worker int * /* O - Pointer to OID array or @code NULL@ on error */
_cupsSNMPStringToOID(const char * src,int * dst,int dstsize)478*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPStringToOID(const char *src, /* I - OID string */
479*5e7646d2SAndroid Build Coastguard Worker int *dst, /* I - OID array */
480*5e7646d2SAndroid Build Coastguard Worker int dstsize)/* I - Number of integers in OID array */
481*5e7646d2SAndroid Build Coastguard Worker {
482*5e7646d2SAndroid Build Coastguard Worker int *dstptr, /* Pointer into OID array */
483*5e7646d2SAndroid Build Coastguard Worker *dstend; /* End of OID array */
484*5e7646d2SAndroid Build Coastguard Worker
485*5e7646d2SAndroid Build Coastguard Worker
486*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPStringToOID(src=\"%s\", dst=%p, dstsize=%d)",
487*5e7646d2SAndroid Build Coastguard Worker src, dst, dstsize));
488*5e7646d2SAndroid Build Coastguard Worker
489*5e7646d2SAndroid Build Coastguard Worker /*
490*5e7646d2SAndroid Build Coastguard Worker * Range check input...
491*5e7646d2SAndroid Build Coastguard Worker */
492*5e7646d2SAndroid Build Coastguard Worker
493*5e7646d2SAndroid Build Coastguard Worker if (!src || !dst || dstsize < 2)
494*5e7646d2SAndroid Build Coastguard Worker return (NULL);
495*5e7646d2SAndroid Build Coastguard Worker
496*5e7646d2SAndroid Build Coastguard Worker /*
497*5e7646d2SAndroid Build Coastguard Worker * Skip leading "."...
498*5e7646d2SAndroid Build Coastguard Worker */
499*5e7646d2SAndroid Build Coastguard Worker
500*5e7646d2SAndroid Build Coastguard Worker if (*src == '.')
501*5e7646d2SAndroid Build Coastguard Worker src ++;
502*5e7646d2SAndroid Build Coastguard Worker
503*5e7646d2SAndroid Build Coastguard Worker /*
504*5e7646d2SAndroid Build Coastguard Worker * Loop to the end of the string...
505*5e7646d2SAndroid Build Coastguard Worker */
506*5e7646d2SAndroid Build Coastguard Worker
507*5e7646d2SAndroid Build Coastguard Worker for (dstend = dst + dstsize - 1, dstptr = dst, *dstptr = 0;
508*5e7646d2SAndroid Build Coastguard Worker *src && dstptr < dstend;
509*5e7646d2SAndroid Build Coastguard Worker src ++)
510*5e7646d2SAndroid Build Coastguard Worker {
511*5e7646d2SAndroid Build Coastguard Worker if (*src == '.')
512*5e7646d2SAndroid Build Coastguard Worker {
513*5e7646d2SAndroid Build Coastguard Worker dstptr ++;
514*5e7646d2SAndroid Build Coastguard Worker *dstptr = 0;
515*5e7646d2SAndroid Build Coastguard Worker }
516*5e7646d2SAndroid Build Coastguard Worker else if (isdigit(*src & 255))
517*5e7646d2SAndroid Build Coastguard Worker *dstptr = *dstptr * 10 + *src - '0';
518*5e7646d2SAndroid Build Coastguard Worker else
519*5e7646d2SAndroid Build Coastguard Worker break;
520*5e7646d2SAndroid Build Coastguard Worker }
521*5e7646d2SAndroid Build Coastguard Worker
522*5e7646d2SAndroid Build Coastguard Worker if (*src)
523*5e7646d2SAndroid Build Coastguard Worker return (NULL);
524*5e7646d2SAndroid Build Coastguard Worker
525*5e7646d2SAndroid Build Coastguard Worker /*
526*5e7646d2SAndroid Build Coastguard Worker * Terminate the end of the OID array and return...
527*5e7646d2SAndroid Build Coastguard Worker */
528*5e7646d2SAndroid Build Coastguard Worker
529*5e7646d2SAndroid Build Coastguard Worker dstptr[1] = -1;
530*5e7646d2SAndroid Build Coastguard Worker
531*5e7646d2SAndroid Build Coastguard Worker return (dst);
532*5e7646d2SAndroid Build Coastguard Worker }
533*5e7646d2SAndroid Build Coastguard Worker
534*5e7646d2SAndroid Build Coastguard Worker
535*5e7646d2SAndroid Build Coastguard Worker /*
536*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPWalk()' - Enumerate a group of OIDs.
537*5e7646d2SAndroid Build Coastguard Worker *
538*5e7646d2SAndroid Build Coastguard Worker * This function queries all of the OIDs with the specified OID prefix,
539*5e7646d2SAndroid Build Coastguard Worker * calling the "cb" function for every response that is received.
540*5e7646d2SAndroid Build Coastguard Worker *
541*5e7646d2SAndroid Build Coastguard Worker * The array pointed to by "prefix" is terminated by the value -1.
542*5e7646d2SAndroid Build Coastguard Worker *
543*5e7646d2SAndroid Build Coastguard Worker * If "timeout" is negative, @code _cupsSNMPWalk@ will wait for a response
544*5e7646d2SAndroid Build Coastguard Worker * indefinitely.
545*5e7646d2SAndroid Build Coastguard Worker */
546*5e7646d2SAndroid Build Coastguard Worker
547*5e7646d2SAndroid Build Coastguard Worker int /* O - Number of OIDs found or -1 on error */
_cupsSNMPWalk(int fd,http_addr_t * address,int version,const char * community,const int * prefix,double timeout,cups_snmp_cb_t cb,void * data)548*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPWalk(int fd, /* I - SNMP socket */
549*5e7646d2SAndroid Build Coastguard Worker http_addr_t *address, /* I - Address to query */
550*5e7646d2SAndroid Build Coastguard Worker int version, /* I - SNMP version */
551*5e7646d2SAndroid Build Coastguard Worker const char *community,/* I - Community name */
552*5e7646d2SAndroid Build Coastguard Worker const int *prefix, /* I - OID prefix */
553*5e7646d2SAndroid Build Coastguard Worker double timeout, /* I - Timeout for each response in seconds */
554*5e7646d2SAndroid Build Coastguard Worker cups_snmp_cb_t cb, /* I - Function to call for each response */
555*5e7646d2SAndroid Build Coastguard Worker void *data) /* I - User data pointer that is passed to the callback function */
556*5e7646d2SAndroid Build Coastguard Worker {
557*5e7646d2SAndroid Build Coastguard Worker int count = 0; /* Number of OIDs found */
558*5e7646d2SAndroid Build Coastguard Worker unsigned request_id = 0; /* Current request ID */
559*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t packet; /* Current response packet */
560*5e7646d2SAndroid Build Coastguard Worker int lastoid[CUPS_SNMP_MAX_OID];
561*5e7646d2SAndroid Build Coastguard Worker /* Last OID we got */
562*5e7646d2SAndroid Build Coastguard Worker
563*5e7646d2SAndroid Build Coastguard Worker
564*5e7646d2SAndroid Build Coastguard Worker /*
565*5e7646d2SAndroid Build Coastguard Worker * Range check input...
566*5e7646d2SAndroid Build Coastguard Worker */
567*5e7646d2SAndroid Build Coastguard Worker
568*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPWalk(fd=%d, address=%p, version=%d, "
569*5e7646d2SAndroid Build Coastguard Worker "community=\"%s\", prefix=%p, timeout=%.1f, cb=%p, data=%p)",
570*5e7646d2SAndroid Build Coastguard Worker fd, address, version, community, prefix, timeout, cb, data));
571*5e7646d2SAndroid Build Coastguard Worker
572*5e7646d2SAndroid Build Coastguard Worker if (fd < 0 || !address || version != CUPS_SNMP_VERSION_1 || !community ||
573*5e7646d2SAndroid Build Coastguard Worker !prefix || !cb)
574*5e7646d2SAndroid Build Coastguard Worker {
575*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPWalk: Returning -1");
576*5e7646d2SAndroid Build Coastguard Worker
577*5e7646d2SAndroid Build Coastguard Worker return (-1);
578*5e7646d2SAndroid Build Coastguard Worker }
579*5e7646d2SAndroid Build Coastguard Worker
580*5e7646d2SAndroid Build Coastguard Worker /*
581*5e7646d2SAndroid Build Coastguard Worker * Copy the OID prefix and then loop until we have no more OIDs...
582*5e7646d2SAndroid Build Coastguard Worker */
583*5e7646d2SAndroid Build Coastguard Worker
584*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPCopyOID(packet.object_name, prefix, CUPS_SNMP_MAX_OID);
585*5e7646d2SAndroid Build Coastguard Worker lastoid[0] = -1;
586*5e7646d2SAndroid Build Coastguard Worker
587*5e7646d2SAndroid Build Coastguard Worker for (;;)
588*5e7646d2SAndroid Build Coastguard Worker {
589*5e7646d2SAndroid Build Coastguard Worker request_id ++;
590*5e7646d2SAndroid Build Coastguard Worker
591*5e7646d2SAndroid Build Coastguard Worker if (!_cupsSNMPWrite(fd, address, version, community,
592*5e7646d2SAndroid Build Coastguard Worker CUPS_ASN1_GET_NEXT_REQUEST, request_id,
593*5e7646d2SAndroid Build Coastguard Worker packet.object_name))
594*5e7646d2SAndroid Build Coastguard Worker {
595*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPWalk: Returning -1");
596*5e7646d2SAndroid Build Coastguard Worker
597*5e7646d2SAndroid Build Coastguard Worker return (-1);
598*5e7646d2SAndroid Build Coastguard Worker }
599*5e7646d2SAndroid Build Coastguard Worker
600*5e7646d2SAndroid Build Coastguard Worker if (!_cupsSNMPRead(fd, &packet, timeout))
601*5e7646d2SAndroid Build Coastguard Worker {
602*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPWalk: Returning -1");
603*5e7646d2SAndroid Build Coastguard Worker
604*5e7646d2SAndroid Build Coastguard Worker return (-1);
605*5e7646d2SAndroid Build Coastguard Worker }
606*5e7646d2SAndroid Build Coastguard Worker
607*5e7646d2SAndroid Build Coastguard Worker if (!_cupsSNMPIsOIDPrefixed(&packet, prefix) ||
608*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPIsOID(&packet, lastoid))
609*5e7646d2SAndroid Build Coastguard Worker {
610*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPWalk: Returning %d", count));
611*5e7646d2SAndroid Build Coastguard Worker
612*5e7646d2SAndroid Build Coastguard Worker return (count);
613*5e7646d2SAndroid Build Coastguard Worker }
614*5e7646d2SAndroid Build Coastguard Worker
615*5e7646d2SAndroid Build Coastguard Worker if (packet.error || packet.error_status)
616*5e7646d2SAndroid Build Coastguard Worker {
617*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsSNMPWalk: Returning %d", count > 0 ? count : -1));
618*5e7646d2SAndroid Build Coastguard Worker
619*5e7646d2SAndroid Build Coastguard Worker return (count > 0 ? count : -1);
620*5e7646d2SAndroid Build Coastguard Worker }
621*5e7646d2SAndroid Build Coastguard Worker
622*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPCopyOID(lastoid, packet.object_name, CUPS_SNMP_MAX_OID);
623*5e7646d2SAndroid Build Coastguard Worker
624*5e7646d2SAndroid Build Coastguard Worker count ++;
625*5e7646d2SAndroid Build Coastguard Worker
626*5e7646d2SAndroid Build Coastguard Worker (*cb)(&packet, data);
627*5e7646d2SAndroid Build Coastguard Worker }
628*5e7646d2SAndroid Build Coastguard Worker }
629*5e7646d2SAndroid Build Coastguard Worker
630*5e7646d2SAndroid Build Coastguard Worker
631*5e7646d2SAndroid Build Coastguard Worker /*
632*5e7646d2SAndroid Build Coastguard Worker * '_cupsSNMPWrite()' - Send an SNMP query packet.
633*5e7646d2SAndroid Build Coastguard Worker *
634*5e7646d2SAndroid Build Coastguard Worker * The array pointed to by "oid" is terminated by the value -1.
635*5e7646d2SAndroid Build Coastguard Worker */
636*5e7646d2SAndroid Build Coastguard Worker
637*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 on success, 0 on error */
_cupsSNMPWrite(int fd,http_addr_t * address,int version,const char * community,cups_asn1_t request_type,const unsigned request_id,const int * oid)638*5e7646d2SAndroid Build Coastguard Worker _cupsSNMPWrite(
639*5e7646d2SAndroid Build Coastguard Worker int fd, /* I - SNMP socket */
640*5e7646d2SAndroid Build Coastguard Worker http_addr_t *address, /* I - Address to send to */
641*5e7646d2SAndroid Build Coastguard Worker int version, /* I - SNMP version */
642*5e7646d2SAndroid Build Coastguard Worker const char *community, /* I - Community name */
643*5e7646d2SAndroid Build Coastguard Worker cups_asn1_t request_type, /* I - Request type */
644*5e7646d2SAndroid Build Coastguard Worker const unsigned request_id, /* I - Request ID */
645*5e7646d2SAndroid Build Coastguard Worker const int *oid) /* I - OID */
646*5e7646d2SAndroid Build Coastguard Worker {
647*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
648*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t packet; /* SNMP message packet */
649*5e7646d2SAndroid Build Coastguard Worker unsigned char buffer[CUPS_SNMP_MAX_PACKET];
650*5e7646d2SAndroid Build Coastguard Worker /* SNMP message buffer */
651*5e7646d2SAndroid Build Coastguard Worker ssize_t bytes; /* Size of message */
652*5e7646d2SAndroid Build Coastguard Worker http_addr_t temp; /* Copy of address */
653*5e7646d2SAndroid Build Coastguard Worker
654*5e7646d2SAndroid Build Coastguard Worker
655*5e7646d2SAndroid Build Coastguard Worker /*
656*5e7646d2SAndroid Build Coastguard Worker * Range check input...
657*5e7646d2SAndroid Build Coastguard Worker */
658*5e7646d2SAndroid Build Coastguard Worker
659*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsSNMPWrite(fd=%d, address=%p, version=%d, "
660*5e7646d2SAndroid Build Coastguard Worker "community=\"%s\", request_type=%d, request_id=%u, oid=%p)",
661*5e7646d2SAndroid Build Coastguard Worker fd, address, version, community, request_type, request_id, oid));
662*5e7646d2SAndroid Build Coastguard Worker
663*5e7646d2SAndroid Build Coastguard Worker if (fd < 0 || !address || version != CUPS_SNMP_VERSION_1 || !community ||
664*5e7646d2SAndroid Build Coastguard Worker (request_type != CUPS_ASN1_GET_REQUEST &&
665*5e7646d2SAndroid Build Coastguard Worker request_type != CUPS_ASN1_GET_NEXT_REQUEST) || request_id < 1 || !oid)
666*5e7646d2SAndroid Build Coastguard Worker {
667*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPWrite: Returning 0 (bad arguments)");
668*5e7646d2SAndroid Build Coastguard Worker
669*5e7646d2SAndroid Build Coastguard Worker return (0);
670*5e7646d2SAndroid Build Coastguard Worker }
671*5e7646d2SAndroid Build Coastguard Worker
672*5e7646d2SAndroid Build Coastguard Worker /*
673*5e7646d2SAndroid Build Coastguard Worker * Create the SNMP message...
674*5e7646d2SAndroid Build Coastguard Worker */
675*5e7646d2SAndroid Build Coastguard Worker
676*5e7646d2SAndroid Build Coastguard Worker memset(&packet, 0, sizeof(packet));
677*5e7646d2SAndroid Build Coastguard Worker
678*5e7646d2SAndroid Build Coastguard Worker packet.version = version;
679*5e7646d2SAndroid Build Coastguard Worker packet.request_type = request_type;
680*5e7646d2SAndroid Build Coastguard Worker packet.request_id = request_id;
681*5e7646d2SAndroid Build Coastguard Worker packet.object_type = CUPS_ASN1_NULL_VALUE;
682*5e7646d2SAndroid Build Coastguard Worker
683*5e7646d2SAndroid Build Coastguard Worker strlcpy(packet.community, community, sizeof(packet.community));
684*5e7646d2SAndroid Build Coastguard Worker
685*5e7646d2SAndroid Build Coastguard Worker for (i = 0; oid[i] >= 0 && i < (CUPS_SNMP_MAX_OID - 1); i ++)
686*5e7646d2SAndroid Build Coastguard Worker packet.object_name[i] = oid[i];
687*5e7646d2SAndroid Build Coastguard Worker packet.object_name[i] = -1;
688*5e7646d2SAndroid Build Coastguard Worker
689*5e7646d2SAndroid Build Coastguard Worker if (oid[i] >= 0)
690*5e7646d2SAndroid Build Coastguard Worker {
691*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPWrite: Returning 0 (OID too big)");
692*5e7646d2SAndroid Build Coastguard Worker
693*5e7646d2SAndroid Build Coastguard Worker errno = E2BIG;
694*5e7646d2SAndroid Build Coastguard Worker return (0);
695*5e7646d2SAndroid Build Coastguard Worker }
696*5e7646d2SAndroid Build Coastguard Worker
697*5e7646d2SAndroid Build Coastguard Worker bytes = asn1_encode_snmp(buffer, sizeof(buffer), &packet);
698*5e7646d2SAndroid Build Coastguard Worker
699*5e7646d2SAndroid Build Coastguard Worker if (bytes < 0)
700*5e7646d2SAndroid Build Coastguard Worker {
701*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsSNMPWrite: Returning 0 (request too big)");
702*5e7646d2SAndroid Build Coastguard Worker
703*5e7646d2SAndroid Build Coastguard Worker errno = E2BIG;
704*5e7646d2SAndroid Build Coastguard Worker return (0);
705*5e7646d2SAndroid Build Coastguard Worker }
706*5e7646d2SAndroid Build Coastguard Worker
707*5e7646d2SAndroid Build Coastguard Worker asn1_debug("DEBUG: OUT ", buffer, (size_t)bytes, 0);
708*5e7646d2SAndroid Build Coastguard Worker
709*5e7646d2SAndroid Build Coastguard Worker /*
710*5e7646d2SAndroid Build Coastguard Worker * Send the message...
711*5e7646d2SAndroid Build Coastguard Worker */
712*5e7646d2SAndroid Build Coastguard Worker
713*5e7646d2SAndroid Build Coastguard Worker temp = *address;
714*5e7646d2SAndroid Build Coastguard Worker
715*5e7646d2SAndroid Build Coastguard Worker _httpAddrSetPort(&temp, CUPS_SNMP_PORT);
716*5e7646d2SAndroid Build Coastguard Worker
717*5e7646d2SAndroid Build Coastguard Worker return (sendto(fd, buffer, (size_t)bytes, 0, (void *)&temp, (socklen_t)httpAddrLength(&temp)) == bytes);
718*5e7646d2SAndroid Build Coastguard Worker }
719*5e7646d2SAndroid Build Coastguard Worker
720*5e7646d2SAndroid Build Coastguard Worker
721*5e7646d2SAndroid Build Coastguard Worker /*
722*5e7646d2SAndroid Build Coastguard Worker * 'asn1_debug()' - Decode an ASN1-encoded message.
723*5e7646d2SAndroid Build Coastguard Worker */
724*5e7646d2SAndroid Build Coastguard Worker
725*5e7646d2SAndroid Build Coastguard Worker static void
asn1_debug(const char * prefix,unsigned char * buffer,size_t len,int indent)726*5e7646d2SAndroid Build Coastguard Worker asn1_debug(const char *prefix, /* I - Prefix string */
727*5e7646d2SAndroid Build Coastguard Worker unsigned char *buffer, /* I - Buffer */
728*5e7646d2SAndroid Build Coastguard Worker size_t len, /* I - Length of buffer */
729*5e7646d2SAndroid Build Coastguard Worker int indent) /* I - Indentation */
730*5e7646d2SAndroid Build Coastguard Worker {
731*5e7646d2SAndroid Build Coastguard Worker size_t i; /* Looping var */
732*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend; /* End of buffer */
733*5e7646d2SAndroid Build Coastguard Worker int integer; /* Number value */
734*5e7646d2SAndroid Build Coastguard Worker int oid[CUPS_SNMP_MAX_OID]; /* OID value */
735*5e7646d2SAndroid Build Coastguard Worker char string[CUPS_SNMP_MAX_STRING];
736*5e7646d2SAndroid Build Coastguard Worker /* String value */
737*5e7646d2SAndroid Build Coastguard Worker unsigned char value_type; /* Type of value */
738*5e7646d2SAndroid Build Coastguard Worker unsigned value_length; /* Length of value */
739*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals(); /* Global data */
740*5e7646d2SAndroid Build Coastguard Worker
741*5e7646d2SAndroid Build Coastguard Worker
742*5e7646d2SAndroid Build Coastguard Worker #ifdef __clang_analyzer__ /* Suppress bogus clang error */
743*5e7646d2SAndroid Build Coastguard Worker memset(string, 0, sizeof(string));
744*5e7646d2SAndroid Build Coastguard Worker #endif /* __clang_analyzer__ */
745*5e7646d2SAndroid Build Coastguard Worker
746*5e7646d2SAndroid Build Coastguard Worker if (cg->snmp_debug <= 0)
747*5e7646d2SAndroid Build Coastguard Worker return;
748*5e7646d2SAndroid Build Coastguard Worker
749*5e7646d2SAndroid Build Coastguard Worker if (cg->snmp_debug > 1 && indent == 0)
750*5e7646d2SAndroid Build Coastguard Worker {
751*5e7646d2SAndroid Build Coastguard Worker /*
752*5e7646d2SAndroid Build Coastguard Worker * Do a hex dump of the packet...
753*5e7646d2SAndroid Build Coastguard Worker */
754*5e7646d2SAndroid Build Coastguard Worker
755*5e7646d2SAndroid Build Coastguard Worker size_t j;
756*5e7646d2SAndroid Build Coastguard Worker
757*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%sHex Dump (%d bytes):\n", prefix, (int)len);
758*5e7646d2SAndroid Build Coastguard Worker
759*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < len; i += 16)
760*5e7646d2SAndroid Build Coastguard Worker {
761*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%04x:", prefix, (unsigned)i);
762*5e7646d2SAndroid Build Coastguard Worker
763*5e7646d2SAndroid Build Coastguard Worker for (j = 0; j < 16 && (i + j) < len; j ++)
764*5e7646d2SAndroid Build Coastguard Worker {
765*5e7646d2SAndroid Build Coastguard Worker if (j && !(j & 3))
766*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, " %02x", buffer[i + j]);
767*5e7646d2SAndroid Build Coastguard Worker else
768*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, " %02x", buffer[i + j]);
769*5e7646d2SAndroid Build Coastguard Worker }
770*5e7646d2SAndroid Build Coastguard Worker
771*5e7646d2SAndroid Build Coastguard Worker while (j < 16)
772*5e7646d2SAndroid Build Coastguard Worker {
773*5e7646d2SAndroid Build Coastguard Worker if (j && !(j & 3))
774*5e7646d2SAndroid Build Coastguard Worker fputs(" ", stderr);
775*5e7646d2SAndroid Build Coastguard Worker else
776*5e7646d2SAndroid Build Coastguard Worker fputs(" ", stderr);
777*5e7646d2SAndroid Build Coastguard Worker
778*5e7646d2SAndroid Build Coastguard Worker j ++;
779*5e7646d2SAndroid Build Coastguard Worker }
780*5e7646d2SAndroid Build Coastguard Worker
781*5e7646d2SAndroid Build Coastguard Worker fputs(" ", stderr);
782*5e7646d2SAndroid Build Coastguard Worker
783*5e7646d2SAndroid Build Coastguard Worker for (j = 0; j < 16 && (i + j) < len; j ++)
784*5e7646d2SAndroid Build Coastguard Worker if (buffer[i + j] < ' ' || buffer[i + j] >= 0x7f)
785*5e7646d2SAndroid Build Coastguard Worker putc('.', stderr);
786*5e7646d2SAndroid Build Coastguard Worker else
787*5e7646d2SAndroid Build Coastguard Worker putc(buffer[i + j], stderr);
788*5e7646d2SAndroid Build Coastguard Worker
789*5e7646d2SAndroid Build Coastguard Worker putc('\n', stderr);
790*5e7646d2SAndroid Build Coastguard Worker }
791*5e7646d2SAndroid Build Coastguard Worker }
792*5e7646d2SAndroid Build Coastguard Worker
793*5e7646d2SAndroid Build Coastguard Worker if (indent == 0)
794*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%sMessage:\n", prefix);
795*5e7646d2SAndroid Build Coastguard Worker
796*5e7646d2SAndroid Build Coastguard Worker bufend = buffer + len;
797*5e7646d2SAndroid Build Coastguard Worker
798*5e7646d2SAndroid Build Coastguard Worker while (buffer < bufend)
799*5e7646d2SAndroid Build Coastguard Worker {
800*5e7646d2SAndroid Build Coastguard Worker /*
801*5e7646d2SAndroid Build Coastguard Worker * Get value type...
802*5e7646d2SAndroid Build Coastguard Worker */
803*5e7646d2SAndroid Build Coastguard Worker
804*5e7646d2SAndroid Build Coastguard Worker value_type = (unsigned char)asn1_get_type(&buffer, bufend);
805*5e7646d2SAndroid Build Coastguard Worker value_length = asn1_get_length(&buffer, bufend);
806*5e7646d2SAndroid Build Coastguard Worker
807*5e7646d2SAndroid Build Coastguard Worker switch (value_type)
808*5e7646d2SAndroid Build Coastguard Worker {
809*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_BOOLEAN :
810*5e7646d2SAndroid Build Coastguard Worker integer = asn1_get_integer(&buffer, bufend, value_length);
811*5e7646d2SAndroid Build Coastguard Worker
812*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sBOOLEAN %d bytes %d\n", prefix, indent, "",
813*5e7646d2SAndroid Build Coastguard Worker value_length, integer);
814*5e7646d2SAndroid Build Coastguard Worker break;
815*5e7646d2SAndroid Build Coastguard Worker
816*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_INTEGER :
817*5e7646d2SAndroid Build Coastguard Worker integer = asn1_get_integer(&buffer, bufend, value_length);
818*5e7646d2SAndroid Build Coastguard Worker
819*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sINTEGER %d bytes %d\n", prefix, indent, "",
820*5e7646d2SAndroid Build Coastguard Worker value_length, integer);
821*5e7646d2SAndroid Build Coastguard Worker break;
822*5e7646d2SAndroid Build Coastguard Worker
823*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_COUNTER :
824*5e7646d2SAndroid Build Coastguard Worker integer = asn1_get_integer(&buffer, bufend, value_length);
825*5e7646d2SAndroid Build Coastguard Worker
826*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sCOUNTER %d bytes %u\n", prefix, indent, "",
827*5e7646d2SAndroid Build Coastguard Worker value_length, (unsigned)integer);
828*5e7646d2SAndroid Build Coastguard Worker break;
829*5e7646d2SAndroid Build Coastguard Worker
830*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_GAUGE :
831*5e7646d2SAndroid Build Coastguard Worker integer = asn1_get_integer(&buffer, bufend, value_length);
832*5e7646d2SAndroid Build Coastguard Worker
833*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sGAUGE %d bytes %u\n", prefix, indent, "",
834*5e7646d2SAndroid Build Coastguard Worker value_length, (unsigned)integer);
835*5e7646d2SAndroid Build Coastguard Worker break;
836*5e7646d2SAndroid Build Coastguard Worker
837*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_TIMETICKS :
838*5e7646d2SAndroid Build Coastguard Worker integer = asn1_get_integer(&buffer, bufend, value_length);
839*5e7646d2SAndroid Build Coastguard Worker
840*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sTIMETICKS %d bytes %u\n", prefix, indent, "",
841*5e7646d2SAndroid Build Coastguard Worker value_length, (unsigned)integer);
842*5e7646d2SAndroid Build Coastguard Worker break;
843*5e7646d2SAndroid Build Coastguard Worker
844*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OCTET_STRING :
845*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sOCTET STRING %d bytes \"%s\"\n", prefix,
846*5e7646d2SAndroid Build Coastguard Worker indent, "", value_length,
847*5e7646d2SAndroid Build Coastguard Worker asn1_get_string(&buffer, bufend, value_length, string,
848*5e7646d2SAndroid Build Coastguard Worker sizeof(string)));
849*5e7646d2SAndroid Build Coastguard Worker break;
850*5e7646d2SAndroid Build Coastguard Worker
851*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_HEX_STRING :
852*5e7646d2SAndroid Build Coastguard Worker asn1_get_string(&buffer, bufend, value_length, string,
853*5e7646d2SAndroid Build Coastguard Worker sizeof(string));
854*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sHex-STRING %d bytes", prefix,
855*5e7646d2SAndroid Build Coastguard Worker indent, "", value_length);
856*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < value_length; i ++)
857*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, " %02X", string[i] & 255);
858*5e7646d2SAndroid Build Coastguard Worker putc('\n', stderr);
859*5e7646d2SAndroid Build Coastguard Worker break;
860*5e7646d2SAndroid Build Coastguard Worker
861*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_NULL_VALUE :
862*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sNULL VALUE %d bytes\n", prefix, indent, "",
863*5e7646d2SAndroid Build Coastguard Worker value_length);
864*5e7646d2SAndroid Build Coastguard Worker
865*5e7646d2SAndroid Build Coastguard Worker buffer += value_length;
866*5e7646d2SAndroid Build Coastguard Worker break;
867*5e7646d2SAndroid Build Coastguard Worker
868*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OID :
869*5e7646d2SAndroid Build Coastguard Worker integer = asn1_get_oid(&buffer, bufend, value_length, oid,
870*5e7646d2SAndroid Build Coastguard Worker CUPS_SNMP_MAX_OID);
871*5e7646d2SAndroid Build Coastguard Worker
872*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sOID %d bytes ", prefix, indent, "",
873*5e7646d2SAndroid Build Coastguard Worker value_length);
874*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < (unsigned)integer; i ++)
875*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, ".%d", oid[i]);
876*5e7646d2SAndroid Build Coastguard Worker putc('\n', stderr);
877*5e7646d2SAndroid Build Coastguard Worker break;
878*5e7646d2SAndroid Build Coastguard Worker
879*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_SEQUENCE :
880*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sSEQUENCE %d bytes\n", prefix, indent, "",
881*5e7646d2SAndroid Build Coastguard Worker value_length);
882*5e7646d2SAndroid Build Coastguard Worker asn1_debug(prefix, buffer, value_length, indent + 4);
883*5e7646d2SAndroid Build Coastguard Worker
884*5e7646d2SAndroid Build Coastguard Worker buffer += value_length;
885*5e7646d2SAndroid Build Coastguard Worker break;
886*5e7646d2SAndroid Build Coastguard Worker
887*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_GET_NEXT_REQUEST :
888*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sGet-Next-Request-PDU %d bytes\n", prefix,
889*5e7646d2SAndroid Build Coastguard Worker indent, "", value_length);
890*5e7646d2SAndroid Build Coastguard Worker asn1_debug(prefix, buffer, value_length, indent + 4);
891*5e7646d2SAndroid Build Coastguard Worker
892*5e7646d2SAndroid Build Coastguard Worker buffer += value_length;
893*5e7646d2SAndroid Build Coastguard Worker break;
894*5e7646d2SAndroid Build Coastguard Worker
895*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_GET_REQUEST :
896*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sGet-Request-PDU %d bytes\n", prefix, indent, "",
897*5e7646d2SAndroid Build Coastguard Worker value_length);
898*5e7646d2SAndroid Build Coastguard Worker asn1_debug(prefix, buffer, value_length, indent + 4);
899*5e7646d2SAndroid Build Coastguard Worker
900*5e7646d2SAndroid Build Coastguard Worker buffer += value_length;
901*5e7646d2SAndroid Build Coastguard Worker break;
902*5e7646d2SAndroid Build Coastguard Worker
903*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_GET_RESPONSE :
904*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sGet-Response-PDU %d bytes\n", prefix, indent,
905*5e7646d2SAndroid Build Coastguard Worker "", value_length);
906*5e7646d2SAndroid Build Coastguard Worker asn1_debug(prefix, buffer, value_length, indent + 4);
907*5e7646d2SAndroid Build Coastguard Worker
908*5e7646d2SAndroid Build Coastguard Worker buffer += value_length;
909*5e7646d2SAndroid Build Coastguard Worker break;
910*5e7646d2SAndroid Build Coastguard Worker
911*5e7646d2SAndroid Build Coastguard Worker default :
912*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s%*sUNKNOWN(%x) %d bytes\n", prefix, indent, "",
913*5e7646d2SAndroid Build Coastguard Worker value_type, value_length);
914*5e7646d2SAndroid Build Coastguard Worker
915*5e7646d2SAndroid Build Coastguard Worker buffer += value_length;
916*5e7646d2SAndroid Build Coastguard Worker break;
917*5e7646d2SAndroid Build Coastguard Worker }
918*5e7646d2SAndroid Build Coastguard Worker }
919*5e7646d2SAndroid Build Coastguard Worker }
920*5e7646d2SAndroid Build Coastguard Worker
921*5e7646d2SAndroid Build Coastguard Worker
922*5e7646d2SAndroid Build Coastguard Worker /*
923*5e7646d2SAndroid Build Coastguard Worker * 'asn1_decode_snmp()' - Decode a SNMP packet.
924*5e7646d2SAndroid Build Coastguard Worker */
925*5e7646d2SAndroid Build Coastguard Worker
926*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on error */
asn1_decode_snmp(unsigned char * buffer,size_t len,cups_snmp_t * packet)927*5e7646d2SAndroid Build Coastguard Worker asn1_decode_snmp(unsigned char *buffer, /* I - Buffer */
928*5e7646d2SAndroid Build Coastguard Worker size_t len, /* I - Size of buffer */
929*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t *packet) /* I - SNMP packet */
930*5e7646d2SAndroid Build Coastguard Worker {
931*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufptr, /* Pointer into the data */
932*5e7646d2SAndroid Build Coastguard Worker *bufend; /* End of data */
933*5e7646d2SAndroid Build Coastguard Worker unsigned length; /* Length of value */
934*5e7646d2SAndroid Build Coastguard Worker
935*5e7646d2SAndroid Build Coastguard Worker
936*5e7646d2SAndroid Build Coastguard Worker /*
937*5e7646d2SAndroid Build Coastguard Worker * Initialize the decoding...
938*5e7646d2SAndroid Build Coastguard Worker */
939*5e7646d2SAndroid Build Coastguard Worker
940*5e7646d2SAndroid Build Coastguard Worker memset(packet, 0, sizeof(cups_snmp_t));
941*5e7646d2SAndroid Build Coastguard Worker packet->object_name[0] = -1;
942*5e7646d2SAndroid Build Coastguard Worker
943*5e7646d2SAndroid Build Coastguard Worker bufptr = buffer;
944*5e7646d2SAndroid Build Coastguard Worker bufend = buffer + len;
945*5e7646d2SAndroid Build Coastguard Worker
946*5e7646d2SAndroid Build Coastguard Worker if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_SEQUENCE)
947*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Packet does not start with SEQUENCE"));
948*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_length(&bufptr, bufend) == 0)
949*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("SEQUENCE uses indefinite length"));
950*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER)
951*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No version number"));
952*5e7646d2SAndroid Build Coastguard Worker else if ((length = asn1_get_length(&bufptr, bufend)) == 0)
953*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Version uses indefinite length"));
954*5e7646d2SAndroid Build Coastguard Worker else if ((packet->version = asn1_get_integer(&bufptr, bufend, length))
955*5e7646d2SAndroid Build Coastguard Worker != CUPS_SNMP_VERSION_1)
956*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Bad SNMP version number"));
957*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_OCTET_STRING)
958*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No community name"));
959*5e7646d2SAndroid Build Coastguard Worker else if ((length = asn1_get_length(&bufptr, bufend)) == 0)
960*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Community name uses indefinite length"));
961*5e7646d2SAndroid Build Coastguard Worker else
962*5e7646d2SAndroid Build Coastguard Worker {
963*5e7646d2SAndroid Build Coastguard Worker asn1_get_string(&bufptr, bufend, length, packet->community,
964*5e7646d2SAndroid Build Coastguard Worker sizeof(packet->community));
965*5e7646d2SAndroid Build Coastguard Worker
966*5e7646d2SAndroid Build Coastguard Worker if ((packet->request_type = (cups_asn1_t)asn1_get_type(&bufptr, bufend))
967*5e7646d2SAndroid Build Coastguard Worker != CUPS_ASN1_GET_RESPONSE)
968*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Packet does not contain a Get-Response-PDU"));
969*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_length(&bufptr, bufend) == 0)
970*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Get-Response-PDU uses indefinite length"));
971*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER)
972*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No request-id"));
973*5e7646d2SAndroid Build Coastguard Worker else if ((length = asn1_get_length(&bufptr, bufend)) == 0)
974*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("request-id uses indefinite length"));
975*5e7646d2SAndroid Build Coastguard Worker else
976*5e7646d2SAndroid Build Coastguard Worker {
977*5e7646d2SAndroid Build Coastguard Worker packet->request_id = (unsigned)asn1_get_integer(&bufptr, bufend, length);
978*5e7646d2SAndroid Build Coastguard Worker
979*5e7646d2SAndroid Build Coastguard Worker if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER)
980*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No error-status"));
981*5e7646d2SAndroid Build Coastguard Worker else if ((length = asn1_get_length(&bufptr, bufend)) == 0)
982*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("error-status uses indefinite length"));
983*5e7646d2SAndroid Build Coastguard Worker else
984*5e7646d2SAndroid Build Coastguard Worker {
985*5e7646d2SAndroid Build Coastguard Worker packet->error_status = asn1_get_integer(&bufptr, bufend, length);
986*5e7646d2SAndroid Build Coastguard Worker
987*5e7646d2SAndroid Build Coastguard Worker if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_INTEGER)
988*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No error-index"));
989*5e7646d2SAndroid Build Coastguard Worker else if ((length = asn1_get_length(&bufptr, bufend)) == 0)
990*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("error-index uses indefinite length"));
991*5e7646d2SAndroid Build Coastguard Worker else
992*5e7646d2SAndroid Build Coastguard Worker {
993*5e7646d2SAndroid Build Coastguard Worker packet->error_index = asn1_get_integer(&bufptr, bufend, length);
994*5e7646d2SAndroid Build Coastguard Worker
995*5e7646d2SAndroid Build Coastguard Worker if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_SEQUENCE)
996*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No variable-bindings SEQUENCE"));
997*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_length(&bufptr, bufend) == 0)
998*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet,
999*5e7646d2SAndroid Build Coastguard Worker _("variable-bindings uses indefinite length"));
1000*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_SEQUENCE)
1001*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No VarBind SEQUENCE"));
1002*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_length(&bufptr, bufend) == 0)
1003*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("VarBind uses indefinite length"));
1004*5e7646d2SAndroid Build Coastguard Worker else if (asn1_get_type(&bufptr, bufend) != CUPS_ASN1_OID)
1005*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("No name OID"));
1006*5e7646d2SAndroid Build Coastguard Worker else if ((length = asn1_get_length(&bufptr, bufend)) == 0)
1007*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Name OID uses indefinite length"));
1008*5e7646d2SAndroid Build Coastguard Worker else
1009*5e7646d2SAndroid Build Coastguard Worker {
1010*5e7646d2SAndroid Build Coastguard Worker asn1_get_oid(&bufptr, bufend, length, packet->object_name,
1011*5e7646d2SAndroid Build Coastguard Worker CUPS_SNMP_MAX_OID);
1012*5e7646d2SAndroid Build Coastguard Worker
1013*5e7646d2SAndroid Build Coastguard Worker packet->object_type = (cups_asn1_t)asn1_get_type(&bufptr, bufend);
1014*5e7646d2SAndroid Build Coastguard Worker
1015*5e7646d2SAndroid Build Coastguard Worker if ((length = asn1_get_length(&bufptr, bufend)) == 0 &&
1016*5e7646d2SAndroid Build Coastguard Worker packet->object_type != CUPS_ASN1_NULL_VALUE &&
1017*5e7646d2SAndroid Build Coastguard Worker packet->object_type != CUPS_ASN1_OCTET_STRING)
1018*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Value uses indefinite length"));
1019*5e7646d2SAndroid Build Coastguard Worker else
1020*5e7646d2SAndroid Build Coastguard Worker {
1021*5e7646d2SAndroid Build Coastguard Worker switch (packet->object_type)
1022*5e7646d2SAndroid Build Coastguard Worker {
1023*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_BOOLEAN :
1024*5e7646d2SAndroid Build Coastguard Worker packet->object_value.boolean =
1025*5e7646d2SAndroid Build Coastguard Worker asn1_get_integer(&bufptr, bufend, length);
1026*5e7646d2SAndroid Build Coastguard Worker break;
1027*5e7646d2SAndroid Build Coastguard Worker
1028*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_INTEGER :
1029*5e7646d2SAndroid Build Coastguard Worker packet->object_value.integer =
1030*5e7646d2SAndroid Build Coastguard Worker asn1_get_integer(&bufptr, bufend, length);
1031*5e7646d2SAndroid Build Coastguard Worker break;
1032*5e7646d2SAndroid Build Coastguard Worker
1033*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_NULL_VALUE :
1034*5e7646d2SAndroid Build Coastguard Worker break;
1035*5e7646d2SAndroid Build Coastguard Worker
1036*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OCTET_STRING :
1037*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_BIT_STRING :
1038*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_HEX_STRING :
1039*5e7646d2SAndroid Build Coastguard Worker packet->object_value.string.num_bytes = length;
1040*5e7646d2SAndroid Build Coastguard Worker asn1_get_string(&bufptr, bufend, length,
1041*5e7646d2SAndroid Build Coastguard Worker (char *)packet->object_value.string.bytes,
1042*5e7646d2SAndroid Build Coastguard Worker sizeof(packet->object_value.string.bytes));
1043*5e7646d2SAndroid Build Coastguard Worker break;
1044*5e7646d2SAndroid Build Coastguard Worker
1045*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OID :
1046*5e7646d2SAndroid Build Coastguard Worker asn1_get_oid(&bufptr, bufend, length,
1047*5e7646d2SAndroid Build Coastguard Worker packet->object_value.oid, CUPS_SNMP_MAX_OID);
1048*5e7646d2SAndroid Build Coastguard Worker break;
1049*5e7646d2SAndroid Build Coastguard Worker
1050*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_COUNTER :
1051*5e7646d2SAndroid Build Coastguard Worker packet->object_value.counter =
1052*5e7646d2SAndroid Build Coastguard Worker asn1_get_integer(&bufptr, bufend, length);
1053*5e7646d2SAndroid Build Coastguard Worker break;
1054*5e7646d2SAndroid Build Coastguard Worker
1055*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_GAUGE :
1056*5e7646d2SAndroid Build Coastguard Worker packet->object_value.gauge =
1057*5e7646d2SAndroid Build Coastguard Worker (unsigned)asn1_get_integer(&bufptr, bufend, length);
1058*5e7646d2SAndroid Build Coastguard Worker break;
1059*5e7646d2SAndroid Build Coastguard Worker
1060*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_TIMETICKS :
1061*5e7646d2SAndroid Build Coastguard Worker packet->object_value.timeticks =
1062*5e7646d2SAndroid Build Coastguard Worker (unsigned)asn1_get_integer(&bufptr, bufend, length);
1063*5e7646d2SAndroid Build Coastguard Worker break;
1064*5e7646d2SAndroid Build Coastguard Worker
1065*5e7646d2SAndroid Build Coastguard Worker default :
1066*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(packet, _("Unsupported value type"));
1067*5e7646d2SAndroid Build Coastguard Worker break;
1068*5e7646d2SAndroid Build Coastguard Worker }
1069*5e7646d2SAndroid Build Coastguard Worker }
1070*5e7646d2SAndroid Build Coastguard Worker }
1071*5e7646d2SAndroid Build Coastguard Worker }
1072*5e7646d2SAndroid Build Coastguard Worker }
1073*5e7646d2SAndroid Build Coastguard Worker }
1074*5e7646d2SAndroid Build Coastguard Worker }
1075*5e7646d2SAndroid Build Coastguard Worker
1076*5e7646d2SAndroid Build Coastguard Worker return (packet->error ? -1 : 0);
1077*5e7646d2SAndroid Build Coastguard Worker }
1078*5e7646d2SAndroid Build Coastguard Worker
1079*5e7646d2SAndroid Build Coastguard Worker
1080*5e7646d2SAndroid Build Coastguard Worker /*
1081*5e7646d2SAndroid Build Coastguard Worker * 'asn1_encode_snmp()' - Encode a SNMP packet.
1082*5e7646d2SAndroid Build Coastguard Worker */
1083*5e7646d2SAndroid Build Coastguard Worker
1084*5e7646d2SAndroid Build Coastguard Worker static int /* O - Length on success, -1 on error */
asn1_encode_snmp(unsigned char * buffer,size_t bufsize,cups_snmp_t * packet)1085*5e7646d2SAndroid Build Coastguard Worker asn1_encode_snmp(unsigned char *buffer, /* I - Buffer */
1086*5e7646d2SAndroid Build Coastguard Worker size_t bufsize, /* I - Size of buffer */
1087*5e7646d2SAndroid Build Coastguard Worker cups_snmp_t *packet) /* I - SNMP packet */
1088*5e7646d2SAndroid Build Coastguard Worker {
1089*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufptr; /* Pointer into buffer */
1090*5e7646d2SAndroid Build Coastguard Worker unsigned total, /* Total length */
1091*5e7646d2SAndroid Build Coastguard Worker msglen, /* Length of entire message */
1092*5e7646d2SAndroid Build Coastguard Worker commlen, /* Length of community string */
1093*5e7646d2SAndroid Build Coastguard Worker reqlen, /* Length of request */
1094*5e7646d2SAndroid Build Coastguard Worker listlen, /* Length of variable list */
1095*5e7646d2SAndroid Build Coastguard Worker varlen, /* Length of variable */
1096*5e7646d2SAndroid Build Coastguard Worker namelen, /* Length of object name OID */
1097*5e7646d2SAndroid Build Coastguard Worker valuelen; /* Length of object value */
1098*5e7646d2SAndroid Build Coastguard Worker
1099*5e7646d2SAndroid Build Coastguard Worker
1100*5e7646d2SAndroid Build Coastguard Worker /*
1101*5e7646d2SAndroid Build Coastguard Worker * Get the lengths of the community string, OID, and message...
1102*5e7646d2SAndroid Build Coastguard Worker */
1103*5e7646d2SAndroid Build Coastguard Worker
1104*5e7646d2SAndroid Build Coastguard Worker
1105*5e7646d2SAndroid Build Coastguard Worker namelen = asn1_size_oid(packet->object_name);
1106*5e7646d2SAndroid Build Coastguard Worker
1107*5e7646d2SAndroid Build Coastguard Worker switch (packet->object_type)
1108*5e7646d2SAndroid Build Coastguard Worker {
1109*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_NULL_VALUE :
1110*5e7646d2SAndroid Build Coastguard Worker valuelen = 0;
1111*5e7646d2SAndroid Build Coastguard Worker break;
1112*5e7646d2SAndroid Build Coastguard Worker
1113*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_BOOLEAN :
1114*5e7646d2SAndroid Build Coastguard Worker valuelen = asn1_size_integer(packet->object_value.boolean);
1115*5e7646d2SAndroid Build Coastguard Worker break;
1116*5e7646d2SAndroid Build Coastguard Worker
1117*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_INTEGER :
1118*5e7646d2SAndroid Build Coastguard Worker valuelen = asn1_size_integer(packet->object_value.integer);
1119*5e7646d2SAndroid Build Coastguard Worker break;
1120*5e7646d2SAndroid Build Coastguard Worker
1121*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OCTET_STRING :
1122*5e7646d2SAndroid Build Coastguard Worker valuelen = packet->object_value.string.num_bytes;
1123*5e7646d2SAndroid Build Coastguard Worker break;
1124*5e7646d2SAndroid Build Coastguard Worker
1125*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OID :
1126*5e7646d2SAndroid Build Coastguard Worker valuelen = asn1_size_oid(packet->object_value.oid);
1127*5e7646d2SAndroid Build Coastguard Worker break;
1128*5e7646d2SAndroid Build Coastguard Worker
1129*5e7646d2SAndroid Build Coastguard Worker default :
1130*5e7646d2SAndroid Build Coastguard Worker packet->error = "Unknown object type";
1131*5e7646d2SAndroid Build Coastguard Worker return (-1);
1132*5e7646d2SAndroid Build Coastguard Worker }
1133*5e7646d2SAndroid Build Coastguard Worker
1134*5e7646d2SAndroid Build Coastguard Worker varlen = 1 + asn1_size_length(namelen) + namelen +
1135*5e7646d2SAndroid Build Coastguard Worker 1 + asn1_size_length(valuelen) + valuelen;
1136*5e7646d2SAndroid Build Coastguard Worker listlen = 1 + asn1_size_length(varlen) + varlen;
1137*5e7646d2SAndroid Build Coastguard Worker reqlen = 2 + asn1_size_integer((int)packet->request_id) +
1138*5e7646d2SAndroid Build Coastguard Worker 2 + asn1_size_integer(packet->error_status) +
1139*5e7646d2SAndroid Build Coastguard Worker 2 + asn1_size_integer(packet->error_index) +
1140*5e7646d2SAndroid Build Coastguard Worker 1 + asn1_size_length(listlen) + listlen;
1141*5e7646d2SAndroid Build Coastguard Worker commlen = (unsigned)strlen(packet->community);
1142*5e7646d2SAndroid Build Coastguard Worker msglen = 2 + asn1_size_integer(packet->version) +
1143*5e7646d2SAndroid Build Coastguard Worker 1 + asn1_size_length(commlen) + commlen +
1144*5e7646d2SAndroid Build Coastguard Worker 1 + asn1_size_length(reqlen) + reqlen;
1145*5e7646d2SAndroid Build Coastguard Worker total = 1 + asn1_size_length(msglen) + msglen;
1146*5e7646d2SAndroid Build Coastguard Worker
1147*5e7646d2SAndroid Build Coastguard Worker if (total > bufsize)
1148*5e7646d2SAndroid Build Coastguard Worker {
1149*5e7646d2SAndroid Build Coastguard Worker packet->error = "Message too large for buffer";
1150*5e7646d2SAndroid Build Coastguard Worker return (-1);
1151*5e7646d2SAndroid Build Coastguard Worker }
1152*5e7646d2SAndroid Build Coastguard Worker
1153*5e7646d2SAndroid Build Coastguard Worker /*
1154*5e7646d2SAndroid Build Coastguard Worker * Then format the message...
1155*5e7646d2SAndroid Build Coastguard Worker */
1156*5e7646d2SAndroid Build Coastguard Worker
1157*5e7646d2SAndroid Build Coastguard Worker bufptr = buffer;
1158*5e7646d2SAndroid Build Coastguard Worker
1159*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = CUPS_ASN1_SEQUENCE; /* SNMPv1 message header */
1160*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(&bufptr, msglen);
1161*5e7646d2SAndroid Build Coastguard Worker
1162*5e7646d2SAndroid Build Coastguard Worker asn1_set_integer(&bufptr, packet->version);
1163*5e7646d2SAndroid Build Coastguard Worker /* version */
1164*5e7646d2SAndroid Build Coastguard Worker
1165*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = CUPS_ASN1_OCTET_STRING; /* community */
1166*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(&bufptr, commlen);
1167*5e7646d2SAndroid Build Coastguard Worker memcpy(bufptr, packet->community, commlen);
1168*5e7646d2SAndroid Build Coastguard Worker bufptr += commlen;
1169*5e7646d2SAndroid Build Coastguard Worker
1170*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = (unsigned char)packet->request_type; /* Get-Request-PDU/Get-Next-Request-PDU */
1171*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(&bufptr, reqlen);
1172*5e7646d2SAndroid Build Coastguard Worker
1173*5e7646d2SAndroid Build Coastguard Worker asn1_set_integer(&bufptr, (int)packet->request_id);
1174*5e7646d2SAndroid Build Coastguard Worker
1175*5e7646d2SAndroid Build Coastguard Worker asn1_set_integer(&bufptr, packet->error_status);
1176*5e7646d2SAndroid Build Coastguard Worker
1177*5e7646d2SAndroid Build Coastguard Worker asn1_set_integer(&bufptr, packet->error_index);
1178*5e7646d2SAndroid Build Coastguard Worker
1179*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = CUPS_ASN1_SEQUENCE; /* variable-bindings */
1180*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(&bufptr, listlen);
1181*5e7646d2SAndroid Build Coastguard Worker
1182*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = CUPS_ASN1_SEQUENCE; /* variable */
1183*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(&bufptr, varlen);
1184*5e7646d2SAndroid Build Coastguard Worker
1185*5e7646d2SAndroid Build Coastguard Worker asn1_set_oid(&bufptr, packet->object_name);
1186*5e7646d2SAndroid Build Coastguard Worker /* ObjectName */
1187*5e7646d2SAndroid Build Coastguard Worker
1188*5e7646d2SAndroid Build Coastguard Worker switch (packet->object_type)
1189*5e7646d2SAndroid Build Coastguard Worker {
1190*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_NULL_VALUE :
1191*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = CUPS_ASN1_NULL_VALUE;
1192*5e7646d2SAndroid Build Coastguard Worker /* ObjectValue */
1193*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = 0; /* Length */
1194*5e7646d2SAndroid Build Coastguard Worker break;
1195*5e7646d2SAndroid Build Coastguard Worker
1196*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_BOOLEAN :
1197*5e7646d2SAndroid Build Coastguard Worker asn1_set_integer(&bufptr, packet->object_value.boolean);
1198*5e7646d2SAndroid Build Coastguard Worker break;
1199*5e7646d2SAndroid Build Coastguard Worker
1200*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_INTEGER :
1201*5e7646d2SAndroid Build Coastguard Worker asn1_set_integer(&bufptr, packet->object_value.integer);
1202*5e7646d2SAndroid Build Coastguard Worker break;
1203*5e7646d2SAndroid Build Coastguard Worker
1204*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OCTET_STRING :
1205*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = CUPS_ASN1_OCTET_STRING;
1206*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(&bufptr, valuelen);
1207*5e7646d2SAndroid Build Coastguard Worker memcpy(bufptr, packet->object_value.string.bytes, valuelen);
1208*5e7646d2SAndroid Build Coastguard Worker bufptr += valuelen;
1209*5e7646d2SAndroid Build Coastguard Worker break;
1210*5e7646d2SAndroid Build Coastguard Worker
1211*5e7646d2SAndroid Build Coastguard Worker case CUPS_ASN1_OID :
1212*5e7646d2SAndroid Build Coastguard Worker asn1_set_oid(&bufptr, packet->object_value.oid);
1213*5e7646d2SAndroid Build Coastguard Worker break;
1214*5e7646d2SAndroid Build Coastguard Worker
1215*5e7646d2SAndroid Build Coastguard Worker default :
1216*5e7646d2SAndroid Build Coastguard Worker break;
1217*5e7646d2SAndroid Build Coastguard Worker }
1218*5e7646d2SAndroid Build Coastguard Worker
1219*5e7646d2SAndroid Build Coastguard Worker return ((int)(bufptr - buffer));
1220*5e7646d2SAndroid Build Coastguard Worker }
1221*5e7646d2SAndroid Build Coastguard Worker
1222*5e7646d2SAndroid Build Coastguard Worker
1223*5e7646d2SAndroid Build Coastguard Worker /*
1224*5e7646d2SAndroid Build Coastguard Worker * 'asn1_get_integer()' - Get an integer value.
1225*5e7646d2SAndroid Build Coastguard Worker */
1226*5e7646d2SAndroid Build Coastguard Worker
1227*5e7646d2SAndroid Build Coastguard Worker static int /* O - Integer value */
asn1_get_integer(unsigned char ** buffer,unsigned char * bufend,unsigned length)1228*5e7646d2SAndroid Build Coastguard Worker asn1_get_integer(
1229*5e7646d2SAndroid Build Coastguard Worker unsigned char **buffer, /* IO - Pointer in buffer */
1230*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend, /* I - End of buffer */
1231*5e7646d2SAndroid Build Coastguard Worker unsigned length) /* I - Length of value */
1232*5e7646d2SAndroid Build Coastguard Worker {
1233*5e7646d2SAndroid Build Coastguard Worker int value; /* Integer value */
1234*5e7646d2SAndroid Build Coastguard Worker
1235*5e7646d2SAndroid Build Coastguard Worker
1236*5e7646d2SAndroid Build Coastguard Worker if (*buffer >= bufend)
1237*5e7646d2SAndroid Build Coastguard Worker return (0);
1238*5e7646d2SAndroid Build Coastguard Worker
1239*5e7646d2SAndroid Build Coastguard Worker if (length > sizeof(int))
1240*5e7646d2SAndroid Build Coastguard Worker {
1241*5e7646d2SAndroid Build Coastguard Worker (*buffer) += length;
1242*5e7646d2SAndroid Build Coastguard Worker return (0);
1243*5e7646d2SAndroid Build Coastguard Worker }
1244*5e7646d2SAndroid Build Coastguard Worker
1245*5e7646d2SAndroid Build Coastguard Worker for (value = (**buffer & 0x80) ? ~0 : 0;
1246*5e7646d2SAndroid Build Coastguard Worker length > 0 && *buffer < bufend;
1247*5e7646d2SAndroid Build Coastguard Worker length --, (*buffer) ++)
1248*5e7646d2SAndroid Build Coastguard Worker value = ((value & 0xffffff) << 8) | **buffer;
1249*5e7646d2SAndroid Build Coastguard Worker
1250*5e7646d2SAndroid Build Coastguard Worker return (value);
1251*5e7646d2SAndroid Build Coastguard Worker }
1252*5e7646d2SAndroid Build Coastguard Worker
1253*5e7646d2SAndroid Build Coastguard Worker
1254*5e7646d2SAndroid Build Coastguard Worker /*
1255*5e7646d2SAndroid Build Coastguard Worker * 'asn1_get_length()' - Get a value length.
1256*5e7646d2SAndroid Build Coastguard Worker */
1257*5e7646d2SAndroid Build Coastguard Worker
1258*5e7646d2SAndroid Build Coastguard Worker static unsigned /* O - Length */
asn1_get_length(unsigned char ** buffer,unsigned char * bufend)1259*5e7646d2SAndroid Build Coastguard Worker asn1_get_length(unsigned char **buffer, /* IO - Pointer in buffer */
1260*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend) /* I - End of buffer */
1261*5e7646d2SAndroid Build Coastguard Worker {
1262*5e7646d2SAndroid Build Coastguard Worker unsigned length; /* Length */
1263*5e7646d2SAndroid Build Coastguard Worker
1264*5e7646d2SAndroid Build Coastguard Worker
1265*5e7646d2SAndroid Build Coastguard Worker if (*buffer >= bufend)
1266*5e7646d2SAndroid Build Coastguard Worker return (0);
1267*5e7646d2SAndroid Build Coastguard Worker
1268*5e7646d2SAndroid Build Coastguard Worker length = **buffer;
1269*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1270*5e7646d2SAndroid Build Coastguard Worker
1271*5e7646d2SAndroid Build Coastguard Worker if (length & 128)
1272*5e7646d2SAndroid Build Coastguard Worker {
1273*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of bytes for length */
1274*5e7646d2SAndroid Build Coastguard Worker
1275*5e7646d2SAndroid Build Coastguard Worker
1276*5e7646d2SAndroid Build Coastguard Worker if ((count = length & 127) > sizeof(unsigned))
1277*5e7646d2SAndroid Build Coastguard Worker {
1278*5e7646d2SAndroid Build Coastguard Worker (*buffer) += count;
1279*5e7646d2SAndroid Build Coastguard Worker return (0);
1280*5e7646d2SAndroid Build Coastguard Worker }
1281*5e7646d2SAndroid Build Coastguard Worker
1282*5e7646d2SAndroid Build Coastguard Worker for (length = 0;
1283*5e7646d2SAndroid Build Coastguard Worker count > 0 && *buffer < bufend;
1284*5e7646d2SAndroid Build Coastguard Worker count --, (*buffer) ++)
1285*5e7646d2SAndroid Build Coastguard Worker length = (length << 8) | **buffer;
1286*5e7646d2SAndroid Build Coastguard Worker }
1287*5e7646d2SAndroid Build Coastguard Worker
1288*5e7646d2SAndroid Build Coastguard Worker return (length);
1289*5e7646d2SAndroid Build Coastguard Worker }
1290*5e7646d2SAndroid Build Coastguard Worker
1291*5e7646d2SAndroid Build Coastguard Worker
1292*5e7646d2SAndroid Build Coastguard Worker /*
1293*5e7646d2SAndroid Build Coastguard Worker * 'asn1_get_oid()' - Get an OID value.
1294*5e7646d2SAndroid Build Coastguard Worker */
1295*5e7646d2SAndroid Build Coastguard Worker
1296*5e7646d2SAndroid Build Coastguard Worker static int /* O - Number of OIDs */
asn1_get_oid(unsigned char ** buffer,unsigned char * bufend,unsigned length,int * oid,int oidsize)1297*5e7646d2SAndroid Build Coastguard Worker asn1_get_oid(
1298*5e7646d2SAndroid Build Coastguard Worker unsigned char **buffer, /* IO - Pointer in buffer */
1299*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend, /* I - End of buffer */
1300*5e7646d2SAndroid Build Coastguard Worker unsigned length, /* I - Length of value */
1301*5e7646d2SAndroid Build Coastguard Worker int *oid, /* I - OID buffer */
1302*5e7646d2SAndroid Build Coastguard Worker int oidsize) /* I - Size of OID buffer */
1303*5e7646d2SAndroid Build Coastguard Worker {
1304*5e7646d2SAndroid Build Coastguard Worker unsigned char *valend; /* End of value */
1305*5e7646d2SAndroid Build Coastguard Worker int *oidptr, /* Current OID */
1306*5e7646d2SAndroid Build Coastguard Worker *oidend; /* End of OID buffer */
1307*5e7646d2SAndroid Build Coastguard Worker int number; /* OID number */
1308*5e7646d2SAndroid Build Coastguard Worker
1309*5e7646d2SAndroid Build Coastguard Worker
1310*5e7646d2SAndroid Build Coastguard Worker if (*buffer >= bufend)
1311*5e7646d2SAndroid Build Coastguard Worker return (0);
1312*5e7646d2SAndroid Build Coastguard Worker
1313*5e7646d2SAndroid Build Coastguard Worker valend = *buffer + length;
1314*5e7646d2SAndroid Build Coastguard Worker oidptr = oid;
1315*5e7646d2SAndroid Build Coastguard Worker oidend = oid + oidsize - 1;
1316*5e7646d2SAndroid Build Coastguard Worker
1317*5e7646d2SAndroid Build Coastguard Worker if (valend > bufend)
1318*5e7646d2SAndroid Build Coastguard Worker valend = bufend;
1319*5e7646d2SAndroid Build Coastguard Worker
1320*5e7646d2SAndroid Build Coastguard Worker number = asn1_get_packed(buffer, bufend);
1321*5e7646d2SAndroid Build Coastguard Worker
1322*5e7646d2SAndroid Build Coastguard Worker if (number < 80)
1323*5e7646d2SAndroid Build Coastguard Worker {
1324*5e7646d2SAndroid Build Coastguard Worker *oidptr++ = number / 40;
1325*5e7646d2SAndroid Build Coastguard Worker number = number % 40;
1326*5e7646d2SAndroid Build Coastguard Worker *oidptr++ = number;
1327*5e7646d2SAndroid Build Coastguard Worker }
1328*5e7646d2SAndroid Build Coastguard Worker else
1329*5e7646d2SAndroid Build Coastguard Worker {
1330*5e7646d2SAndroid Build Coastguard Worker *oidptr++ = 2;
1331*5e7646d2SAndroid Build Coastguard Worker number -= 80;
1332*5e7646d2SAndroid Build Coastguard Worker *oidptr++ = number;
1333*5e7646d2SAndroid Build Coastguard Worker }
1334*5e7646d2SAndroid Build Coastguard Worker
1335*5e7646d2SAndroid Build Coastguard Worker while (*buffer < valend)
1336*5e7646d2SAndroid Build Coastguard Worker {
1337*5e7646d2SAndroid Build Coastguard Worker number = asn1_get_packed(buffer, bufend);
1338*5e7646d2SAndroid Build Coastguard Worker
1339*5e7646d2SAndroid Build Coastguard Worker if (oidptr < oidend)
1340*5e7646d2SAndroid Build Coastguard Worker *oidptr++ = number;
1341*5e7646d2SAndroid Build Coastguard Worker }
1342*5e7646d2SAndroid Build Coastguard Worker
1343*5e7646d2SAndroid Build Coastguard Worker *oidptr = -1;
1344*5e7646d2SAndroid Build Coastguard Worker
1345*5e7646d2SAndroid Build Coastguard Worker return ((int)(oidptr - oid));
1346*5e7646d2SAndroid Build Coastguard Worker }
1347*5e7646d2SAndroid Build Coastguard Worker
1348*5e7646d2SAndroid Build Coastguard Worker
1349*5e7646d2SAndroid Build Coastguard Worker /*
1350*5e7646d2SAndroid Build Coastguard Worker * 'asn1_get_packed()' - Get a packed integer value.
1351*5e7646d2SAndroid Build Coastguard Worker */
1352*5e7646d2SAndroid Build Coastguard Worker
1353*5e7646d2SAndroid Build Coastguard Worker static int /* O - Value */
asn1_get_packed(unsigned char ** buffer,unsigned char * bufend)1354*5e7646d2SAndroid Build Coastguard Worker asn1_get_packed(
1355*5e7646d2SAndroid Build Coastguard Worker unsigned char **buffer, /* IO - Pointer in buffer */
1356*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend) /* I - End of buffer */
1357*5e7646d2SAndroid Build Coastguard Worker {
1358*5e7646d2SAndroid Build Coastguard Worker int value; /* Value */
1359*5e7646d2SAndroid Build Coastguard Worker
1360*5e7646d2SAndroid Build Coastguard Worker
1361*5e7646d2SAndroid Build Coastguard Worker if (*buffer >= bufend)
1362*5e7646d2SAndroid Build Coastguard Worker return (0);
1363*5e7646d2SAndroid Build Coastguard Worker
1364*5e7646d2SAndroid Build Coastguard Worker value = 0;
1365*5e7646d2SAndroid Build Coastguard Worker
1366*5e7646d2SAndroid Build Coastguard Worker while (*buffer < bufend && (**buffer & 128))
1367*5e7646d2SAndroid Build Coastguard Worker {
1368*5e7646d2SAndroid Build Coastguard Worker value = (value << 7) | (**buffer & 127);
1369*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1370*5e7646d2SAndroid Build Coastguard Worker }
1371*5e7646d2SAndroid Build Coastguard Worker
1372*5e7646d2SAndroid Build Coastguard Worker if (*buffer < bufend)
1373*5e7646d2SAndroid Build Coastguard Worker {
1374*5e7646d2SAndroid Build Coastguard Worker value = (value << 7) | **buffer;
1375*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1376*5e7646d2SAndroid Build Coastguard Worker }
1377*5e7646d2SAndroid Build Coastguard Worker
1378*5e7646d2SAndroid Build Coastguard Worker return (value);
1379*5e7646d2SAndroid Build Coastguard Worker }
1380*5e7646d2SAndroid Build Coastguard Worker
1381*5e7646d2SAndroid Build Coastguard Worker
1382*5e7646d2SAndroid Build Coastguard Worker /*
1383*5e7646d2SAndroid Build Coastguard Worker * 'asn1_get_string()' - Get a string value.
1384*5e7646d2SAndroid Build Coastguard Worker */
1385*5e7646d2SAndroid Build Coastguard Worker
1386*5e7646d2SAndroid Build Coastguard Worker static char * /* O - String */
asn1_get_string(unsigned char ** buffer,unsigned char * bufend,unsigned length,char * string,size_t strsize)1387*5e7646d2SAndroid Build Coastguard Worker asn1_get_string(
1388*5e7646d2SAndroid Build Coastguard Worker unsigned char **buffer, /* IO - Pointer in buffer */
1389*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend, /* I - End of buffer */
1390*5e7646d2SAndroid Build Coastguard Worker unsigned length, /* I - Value length */
1391*5e7646d2SAndroid Build Coastguard Worker char *string, /* I - String buffer */
1392*5e7646d2SAndroid Build Coastguard Worker size_t strsize) /* I - String buffer size */
1393*5e7646d2SAndroid Build Coastguard Worker {
1394*5e7646d2SAndroid Build Coastguard Worker if (*buffer >= bufend)
1395*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1396*5e7646d2SAndroid Build Coastguard Worker
1397*5e7646d2SAndroid Build Coastguard Worker if (length > (unsigned)(bufend - *buffer))
1398*5e7646d2SAndroid Build Coastguard Worker length = (unsigned)(bufend - *buffer);
1399*5e7646d2SAndroid Build Coastguard Worker
1400*5e7646d2SAndroid Build Coastguard Worker if (length < strsize)
1401*5e7646d2SAndroid Build Coastguard Worker {
1402*5e7646d2SAndroid Build Coastguard Worker /*
1403*5e7646d2SAndroid Build Coastguard Worker * String is smaller than the buffer...
1404*5e7646d2SAndroid Build Coastguard Worker */
1405*5e7646d2SAndroid Build Coastguard Worker
1406*5e7646d2SAndroid Build Coastguard Worker if (length > 0)
1407*5e7646d2SAndroid Build Coastguard Worker memcpy(string, *buffer, length);
1408*5e7646d2SAndroid Build Coastguard Worker
1409*5e7646d2SAndroid Build Coastguard Worker string[length] = '\0';
1410*5e7646d2SAndroid Build Coastguard Worker }
1411*5e7646d2SAndroid Build Coastguard Worker else
1412*5e7646d2SAndroid Build Coastguard Worker {
1413*5e7646d2SAndroid Build Coastguard Worker /*
1414*5e7646d2SAndroid Build Coastguard Worker * String is larger than the buffer...
1415*5e7646d2SAndroid Build Coastguard Worker */
1416*5e7646d2SAndroid Build Coastguard Worker
1417*5e7646d2SAndroid Build Coastguard Worker memcpy(string, *buffer, strsize - 1);
1418*5e7646d2SAndroid Build Coastguard Worker string[strsize - 1] = '\0';
1419*5e7646d2SAndroid Build Coastguard Worker }
1420*5e7646d2SAndroid Build Coastguard Worker
1421*5e7646d2SAndroid Build Coastguard Worker if (length > 0)
1422*5e7646d2SAndroid Build Coastguard Worker (*buffer) += length;
1423*5e7646d2SAndroid Build Coastguard Worker
1424*5e7646d2SAndroid Build Coastguard Worker return (string);
1425*5e7646d2SAndroid Build Coastguard Worker }
1426*5e7646d2SAndroid Build Coastguard Worker
1427*5e7646d2SAndroid Build Coastguard Worker
1428*5e7646d2SAndroid Build Coastguard Worker /*
1429*5e7646d2SAndroid Build Coastguard Worker * 'asn1_get_type()' - Get a value type.
1430*5e7646d2SAndroid Build Coastguard Worker */
1431*5e7646d2SAndroid Build Coastguard Worker
1432*5e7646d2SAndroid Build Coastguard Worker static int /* O - Type */
asn1_get_type(unsigned char ** buffer,unsigned char * bufend)1433*5e7646d2SAndroid Build Coastguard Worker asn1_get_type(unsigned char **buffer, /* IO - Pointer in buffer */
1434*5e7646d2SAndroid Build Coastguard Worker unsigned char *bufend) /* I - End of buffer */
1435*5e7646d2SAndroid Build Coastguard Worker {
1436*5e7646d2SAndroid Build Coastguard Worker int type; /* Type */
1437*5e7646d2SAndroid Build Coastguard Worker
1438*5e7646d2SAndroid Build Coastguard Worker
1439*5e7646d2SAndroid Build Coastguard Worker if (*buffer >= bufend)
1440*5e7646d2SAndroid Build Coastguard Worker return (0);
1441*5e7646d2SAndroid Build Coastguard Worker
1442*5e7646d2SAndroid Build Coastguard Worker type = **buffer;
1443*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1444*5e7646d2SAndroid Build Coastguard Worker
1445*5e7646d2SAndroid Build Coastguard Worker if ((type & 31) == 31)
1446*5e7646d2SAndroid Build Coastguard Worker type = asn1_get_packed(buffer, bufend);
1447*5e7646d2SAndroid Build Coastguard Worker
1448*5e7646d2SAndroid Build Coastguard Worker return (type);
1449*5e7646d2SAndroid Build Coastguard Worker }
1450*5e7646d2SAndroid Build Coastguard Worker
1451*5e7646d2SAndroid Build Coastguard Worker
1452*5e7646d2SAndroid Build Coastguard Worker /*
1453*5e7646d2SAndroid Build Coastguard Worker * 'asn1_set_integer()' - Set an integer value.
1454*5e7646d2SAndroid Build Coastguard Worker */
1455*5e7646d2SAndroid Build Coastguard Worker
1456*5e7646d2SAndroid Build Coastguard Worker static void
asn1_set_integer(unsigned char ** buffer,int integer)1457*5e7646d2SAndroid Build Coastguard Worker asn1_set_integer(unsigned char **buffer,/* IO - Pointer in buffer */
1458*5e7646d2SAndroid Build Coastguard Worker int integer) /* I - Integer value */
1459*5e7646d2SAndroid Build Coastguard Worker {
1460*5e7646d2SAndroid Build Coastguard Worker **buffer = CUPS_ASN1_INTEGER;
1461*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1462*5e7646d2SAndroid Build Coastguard Worker
1463*5e7646d2SAndroid Build Coastguard Worker if (integer > 0x7fffff || integer < -0x800000)
1464*5e7646d2SAndroid Build Coastguard Worker {
1465*5e7646d2SAndroid Build Coastguard Worker **buffer = 4;
1466*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1467*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)(integer >> 24);
1468*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1469*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)(integer >> 16);
1470*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1471*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)(integer >> 8);
1472*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1473*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)integer;
1474*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1475*5e7646d2SAndroid Build Coastguard Worker }
1476*5e7646d2SAndroid Build Coastguard Worker else if (integer > 0x7fff || integer < -0x8000)
1477*5e7646d2SAndroid Build Coastguard Worker {
1478*5e7646d2SAndroid Build Coastguard Worker **buffer = 3;
1479*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1480*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)(integer >> 16);
1481*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1482*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)(integer >> 8);
1483*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1484*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)integer;
1485*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1486*5e7646d2SAndroid Build Coastguard Worker }
1487*5e7646d2SAndroid Build Coastguard Worker else if (integer > 0x7f || integer < -0x80)
1488*5e7646d2SAndroid Build Coastguard Worker {
1489*5e7646d2SAndroid Build Coastguard Worker **buffer = 2;
1490*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1491*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)(integer >> 8);
1492*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1493*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)integer;
1494*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1495*5e7646d2SAndroid Build Coastguard Worker }
1496*5e7646d2SAndroid Build Coastguard Worker else
1497*5e7646d2SAndroid Build Coastguard Worker {
1498*5e7646d2SAndroid Build Coastguard Worker **buffer = 1;
1499*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1500*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)integer;
1501*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1502*5e7646d2SAndroid Build Coastguard Worker }
1503*5e7646d2SAndroid Build Coastguard Worker }
1504*5e7646d2SAndroid Build Coastguard Worker
1505*5e7646d2SAndroid Build Coastguard Worker
1506*5e7646d2SAndroid Build Coastguard Worker /*
1507*5e7646d2SAndroid Build Coastguard Worker * 'asn1_set_length()' - Set a value length.
1508*5e7646d2SAndroid Build Coastguard Worker */
1509*5e7646d2SAndroid Build Coastguard Worker
1510*5e7646d2SAndroid Build Coastguard Worker static void
asn1_set_length(unsigned char ** buffer,unsigned length)1511*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(unsigned char **buffer, /* IO - Pointer in buffer */
1512*5e7646d2SAndroid Build Coastguard Worker unsigned length) /* I - Length value */
1513*5e7646d2SAndroid Build Coastguard Worker {
1514*5e7646d2SAndroid Build Coastguard Worker if (length > 255)
1515*5e7646d2SAndroid Build Coastguard Worker {
1516*5e7646d2SAndroid Build Coastguard Worker **buffer = 0x82; /* 2-byte length */
1517*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1518*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)(length >> 8);
1519*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1520*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)length;
1521*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1522*5e7646d2SAndroid Build Coastguard Worker }
1523*5e7646d2SAndroid Build Coastguard Worker else if (length > 127)
1524*5e7646d2SAndroid Build Coastguard Worker {
1525*5e7646d2SAndroid Build Coastguard Worker **buffer = 0x81; /* 1-byte length */
1526*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1527*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)length;
1528*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1529*5e7646d2SAndroid Build Coastguard Worker }
1530*5e7646d2SAndroid Build Coastguard Worker else
1531*5e7646d2SAndroid Build Coastguard Worker {
1532*5e7646d2SAndroid Build Coastguard Worker **buffer = (unsigned char)length; /* Length */
1533*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1534*5e7646d2SAndroid Build Coastguard Worker }
1535*5e7646d2SAndroid Build Coastguard Worker }
1536*5e7646d2SAndroid Build Coastguard Worker
1537*5e7646d2SAndroid Build Coastguard Worker
1538*5e7646d2SAndroid Build Coastguard Worker /*
1539*5e7646d2SAndroid Build Coastguard Worker * 'asn1_set_oid()' - Set an OID value.
1540*5e7646d2SAndroid Build Coastguard Worker */
1541*5e7646d2SAndroid Build Coastguard Worker
1542*5e7646d2SAndroid Build Coastguard Worker static void
asn1_set_oid(unsigned char ** buffer,const int * oid)1543*5e7646d2SAndroid Build Coastguard Worker asn1_set_oid(unsigned char **buffer, /* IO - Pointer in buffer */
1544*5e7646d2SAndroid Build Coastguard Worker const int *oid) /* I - OID value */
1545*5e7646d2SAndroid Build Coastguard Worker {
1546*5e7646d2SAndroid Build Coastguard Worker **buffer = CUPS_ASN1_OID;
1547*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1548*5e7646d2SAndroid Build Coastguard Worker
1549*5e7646d2SAndroid Build Coastguard Worker asn1_set_length(buffer, asn1_size_oid(oid));
1550*5e7646d2SAndroid Build Coastguard Worker
1551*5e7646d2SAndroid Build Coastguard Worker if (oid[1] < 0)
1552*5e7646d2SAndroid Build Coastguard Worker {
1553*5e7646d2SAndroid Build Coastguard Worker asn1_set_packed(buffer, oid[0] * 40);
1554*5e7646d2SAndroid Build Coastguard Worker return;
1555*5e7646d2SAndroid Build Coastguard Worker }
1556*5e7646d2SAndroid Build Coastguard Worker
1557*5e7646d2SAndroid Build Coastguard Worker asn1_set_packed(buffer, oid[0] * 40 + oid[1]);
1558*5e7646d2SAndroid Build Coastguard Worker
1559*5e7646d2SAndroid Build Coastguard Worker for (oid += 2; *oid >= 0; oid ++)
1560*5e7646d2SAndroid Build Coastguard Worker asn1_set_packed(buffer, *oid);
1561*5e7646d2SAndroid Build Coastguard Worker }
1562*5e7646d2SAndroid Build Coastguard Worker
1563*5e7646d2SAndroid Build Coastguard Worker
1564*5e7646d2SAndroid Build Coastguard Worker /*
1565*5e7646d2SAndroid Build Coastguard Worker * 'asn1_set_packed()' - Set a packed integer value.
1566*5e7646d2SAndroid Build Coastguard Worker */
1567*5e7646d2SAndroid Build Coastguard Worker
1568*5e7646d2SAndroid Build Coastguard Worker static void
asn1_set_packed(unsigned char ** buffer,int integer)1569*5e7646d2SAndroid Build Coastguard Worker asn1_set_packed(unsigned char **buffer, /* IO - Pointer in buffer */
1570*5e7646d2SAndroid Build Coastguard Worker int integer) /* I - Integer value */
1571*5e7646d2SAndroid Build Coastguard Worker {
1572*5e7646d2SAndroid Build Coastguard Worker if (integer > 0xfffffff)
1573*5e7646d2SAndroid Build Coastguard Worker {
1574*5e7646d2SAndroid Build Coastguard Worker **buffer = ((integer >> 28) & 0x7f) | 0x80;
1575*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1576*5e7646d2SAndroid Build Coastguard Worker }
1577*5e7646d2SAndroid Build Coastguard Worker
1578*5e7646d2SAndroid Build Coastguard Worker if (integer > 0x1fffff)
1579*5e7646d2SAndroid Build Coastguard Worker {
1580*5e7646d2SAndroid Build Coastguard Worker **buffer = ((integer >> 21) & 0x7f) | 0x80;
1581*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1582*5e7646d2SAndroid Build Coastguard Worker }
1583*5e7646d2SAndroid Build Coastguard Worker
1584*5e7646d2SAndroid Build Coastguard Worker if (integer > 0x3fff)
1585*5e7646d2SAndroid Build Coastguard Worker {
1586*5e7646d2SAndroid Build Coastguard Worker **buffer = ((integer >> 14) & 0x7f) | 0x80;
1587*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1588*5e7646d2SAndroid Build Coastguard Worker }
1589*5e7646d2SAndroid Build Coastguard Worker
1590*5e7646d2SAndroid Build Coastguard Worker if (integer > 0x7f)
1591*5e7646d2SAndroid Build Coastguard Worker {
1592*5e7646d2SAndroid Build Coastguard Worker **buffer = ((integer >> 7) & 0x7f) | 0x80;
1593*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1594*5e7646d2SAndroid Build Coastguard Worker }
1595*5e7646d2SAndroid Build Coastguard Worker
1596*5e7646d2SAndroid Build Coastguard Worker **buffer = integer & 0x7f;
1597*5e7646d2SAndroid Build Coastguard Worker (*buffer) ++;
1598*5e7646d2SAndroid Build Coastguard Worker }
1599*5e7646d2SAndroid Build Coastguard Worker
1600*5e7646d2SAndroid Build Coastguard Worker
1601*5e7646d2SAndroid Build Coastguard Worker /*
1602*5e7646d2SAndroid Build Coastguard Worker * 'asn1_size_integer()' - Figure out the number of bytes needed for an
1603*5e7646d2SAndroid Build Coastguard Worker * integer value.
1604*5e7646d2SAndroid Build Coastguard Worker */
1605*5e7646d2SAndroid Build Coastguard Worker
1606*5e7646d2SAndroid Build Coastguard Worker static unsigned /* O - Size in bytes */
asn1_size_integer(int integer)1607*5e7646d2SAndroid Build Coastguard Worker asn1_size_integer(int integer) /* I - Integer value */
1608*5e7646d2SAndroid Build Coastguard Worker {
1609*5e7646d2SAndroid Build Coastguard Worker if (integer > 0x7fffff || integer < -0x800000)
1610*5e7646d2SAndroid Build Coastguard Worker return (4);
1611*5e7646d2SAndroid Build Coastguard Worker else if (integer > 0x7fff || integer < -0x8000)
1612*5e7646d2SAndroid Build Coastguard Worker return (3);
1613*5e7646d2SAndroid Build Coastguard Worker else if (integer > 0x7f || integer < -0x80)
1614*5e7646d2SAndroid Build Coastguard Worker return (2);
1615*5e7646d2SAndroid Build Coastguard Worker else
1616*5e7646d2SAndroid Build Coastguard Worker return (1);
1617*5e7646d2SAndroid Build Coastguard Worker }
1618*5e7646d2SAndroid Build Coastguard Worker
1619*5e7646d2SAndroid Build Coastguard Worker
1620*5e7646d2SAndroid Build Coastguard Worker /*
1621*5e7646d2SAndroid Build Coastguard Worker * 'asn1_size_length()' - Figure out the number of bytes needed for a
1622*5e7646d2SAndroid Build Coastguard Worker * length value.
1623*5e7646d2SAndroid Build Coastguard Worker */
1624*5e7646d2SAndroid Build Coastguard Worker
1625*5e7646d2SAndroid Build Coastguard Worker static unsigned /* O - Size in bytes */
asn1_size_length(unsigned length)1626*5e7646d2SAndroid Build Coastguard Worker asn1_size_length(unsigned length) /* I - Length value */
1627*5e7646d2SAndroid Build Coastguard Worker {
1628*5e7646d2SAndroid Build Coastguard Worker if (length > 0xff)
1629*5e7646d2SAndroid Build Coastguard Worker return (3);
1630*5e7646d2SAndroid Build Coastguard Worker else if (length > 0x7f)
1631*5e7646d2SAndroid Build Coastguard Worker return (2);
1632*5e7646d2SAndroid Build Coastguard Worker else
1633*5e7646d2SAndroid Build Coastguard Worker return (1);
1634*5e7646d2SAndroid Build Coastguard Worker }
1635*5e7646d2SAndroid Build Coastguard Worker
1636*5e7646d2SAndroid Build Coastguard Worker
1637*5e7646d2SAndroid Build Coastguard Worker /*
1638*5e7646d2SAndroid Build Coastguard Worker * 'asn1_size_oid()' - Figure out the number of bytes needed for an
1639*5e7646d2SAndroid Build Coastguard Worker * OID value.
1640*5e7646d2SAndroid Build Coastguard Worker */
1641*5e7646d2SAndroid Build Coastguard Worker
1642*5e7646d2SAndroid Build Coastguard Worker static unsigned /* O - Size in bytes */
asn1_size_oid(const int * oid)1643*5e7646d2SAndroid Build Coastguard Worker asn1_size_oid(const int *oid) /* I - OID value */
1644*5e7646d2SAndroid Build Coastguard Worker {
1645*5e7646d2SAndroid Build Coastguard Worker unsigned length; /* Length of value */
1646*5e7646d2SAndroid Build Coastguard Worker
1647*5e7646d2SAndroid Build Coastguard Worker
1648*5e7646d2SAndroid Build Coastguard Worker if (oid[1] < 0)
1649*5e7646d2SAndroid Build Coastguard Worker return (asn1_size_packed(oid[0] * 40));
1650*5e7646d2SAndroid Build Coastguard Worker
1651*5e7646d2SAndroid Build Coastguard Worker for (length = asn1_size_packed(oid[0] * 40 + oid[1]), oid += 2;
1652*5e7646d2SAndroid Build Coastguard Worker *oid >= 0;
1653*5e7646d2SAndroid Build Coastguard Worker oid ++)
1654*5e7646d2SAndroid Build Coastguard Worker length += asn1_size_packed(*oid);
1655*5e7646d2SAndroid Build Coastguard Worker
1656*5e7646d2SAndroid Build Coastguard Worker return (length);
1657*5e7646d2SAndroid Build Coastguard Worker }
1658*5e7646d2SAndroid Build Coastguard Worker
1659*5e7646d2SAndroid Build Coastguard Worker
1660*5e7646d2SAndroid Build Coastguard Worker /*
1661*5e7646d2SAndroid Build Coastguard Worker * 'asn1_size_packed()' - Figure out the number of bytes needed for a
1662*5e7646d2SAndroid Build Coastguard Worker * packed integer value.
1663*5e7646d2SAndroid Build Coastguard Worker */
1664*5e7646d2SAndroid Build Coastguard Worker
1665*5e7646d2SAndroid Build Coastguard Worker static unsigned /* O - Size in bytes */
asn1_size_packed(int integer)1666*5e7646d2SAndroid Build Coastguard Worker asn1_size_packed(int integer) /* I - Integer value */
1667*5e7646d2SAndroid Build Coastguard Worker {
1668*5e7646d2SAndroid Build Coastguard Worker if (integer > 0xfffffff)
1669*5e7646d2SAndroid Build Coastguard Worker return (5);
1670*5e7646d2SAndroid Build Coastguard Worker else if (integer > 0x1fffff)
1671*5e7646d2SAndroid Build Coastguard Worker return (4);
1672*5e7646d2SAndroid Build Coastguard Worker else if (integer > 0x3fff)
1673*5e7646d2SAndroid Build Coastguard Worker return (3);
1674*5e7646d2SAndroid Build Coastguard Worker else if (integer > 0x7f)
1675*5e7646d2SAndroid Build Coastguard Worker return (2);
1676*5e7646d2SAndroid Build Coastguard Worker else
1677*5e7646d2SAndroid Build Coastguard Worker return (1);
1678*5e7646d2SAndroid Build Coastguard Worker }
1679*5e7646d2SAndroid Build Coastguard Worker
1680*5e7646d2SAndroid Build Coastguard Worker
1681*5e7646d2SAndroid Build Coastguard Worker /*
1682*5e7646d2SAndroid Build Coastguard Worker * 'snmp_set_error()' - Set the localized error for a packet.
1683*5e7646d2SAndroid Build Coastguard Worker */
1684*5e7646d2SAndroid Build Coastguard Worker
1685*5e7646d2SAndroid Build Coastguard Worker static void
snmp_set_error(cups_snmp_t * packet,const char * message)1686*5e7646d2SAndroid Build Coastguard Worker snmp_set_error(cups_snmp_t *packet, /* I - Packet */
1687*5e7646d2SAndroid Build Coastguard Worker const char *message) /* I - Error message */
1688*5e7646d2SAndroid Build Coastguard Worker {
1689*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals(); /* Global data */
1690*5e7646d2SAndroid Build Coastguard Worker
1691*5e7646d2SAndroid Build Coastguard Worker
1692*5e7646d2SAndroid Build Coastguard Worker if (!cg->lang_default)
1693*5e7646d2SAndroid Build Coastguard Worker cg->lang_default = cupsLangDefault();
1694*5e7646d2SAndroid Build Coastguard Worker
1695*5e7646d2SAndroid Build Coastguard Worker packet->error = _cupsLangString(cg->lang_default, message);
1696*5e7646d2SAndroid Build Coastguard Worker }
1697