xref: /aosp_15_r20/external/libcups/cups/snmp.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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