1 /*
2  * SNMP test program for CUPS.
3  *
4  * Copyright 2008-2014 by Apple Inc.
5  *
6  * These coded instructions, statements, and computer programs are the
7  * property of Apple Inc. and are protected by Federal copyright
8  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
9  * which should have been included with this file.  If this file is
10  * missing or damaged, see the license at "http://www.cups.org/".
11  *
12  * This file is subject to the Apple OS-Developed Software exception.
13  */
14 
15 /*
16  * Include necessary headers...
17  */
18 
19 #include "cups-private.h"
20 #include "snmp-private.h"
21 
22 
23 /*
24  * Local functions...
25  */
26 
27 static void	print_packet(cups_snmp_t *packet, void *data);
28 static int	show_oid(int fd, const char *community,
29 		         http_addr_t *addr, const char *s, int walk);
30 static void	usage(void) __attribute__((noreturn));
31 
32 
33 /*
34  * 'main()' - Main entry.
35  */
36 
37 int					/* O - Exit status */
main(int argc,char * argv[])38 main(int  argc,				/* I - Number of command-line args */
39      char *argv[])			/* I - Command-line arguments */
40 {
41   int			i;		/* Looping var */
42   int			fd = -1;	/* SNMP socket */
43   http_addrlist_t	*host = NULL;	/* Address of host */
44   int			walk = 0;	/* Walk OIDs? */
45   char			*oid = NULL;	/* Last OID shown */
46   const char		*community;	/* Community name */
47 
48 
49   fputs("_cupsSNMPDefaultCommunity: ", stdout);
50 
51   if ((community = _cupsSNMPDefaultCommunity()) == NULL)
52   {
53     puts("FAIL (NULL community name)");
54     return (1);
55   }
56 
57   printf("PASS (%s)\n", community);
58 
59  /*
60   * Query OIDs from the command-line...
61   */
62 
63   for (i = 1; i < argc; i ++)
64     if (!strcmp(argv[i], "-c"))
65     {
66       i ++;
67 
68       if (i >= argc)
69         usage();
70       else
71         community = argv[i];
72     }
73     else if (!strcmp(argv[i], "-d"))
74       _cupsSNMPSetDebug(10);
75     else if (!strcmp(argv[i], "-w"))
76       walk = 1;
77     else if (!host)
78     {
79       if ((host = httpAddrGetList(argv[i], AF_UNSPEC, "161")) == NULL)
80       {
81 	printf("testsnmp: Unable to find \"%s\"!\n", argv[1]);
82 	return (1);
83       }
84 
85       if (fd < 0)
86       {
87 	fputs("_cupsSNMPOpen: ", stdout);
88 
89 	if ((fd = _cupsSNMPOpen(host->addr.addr.sa_family)) < 0)
90 	{
91 	  printf("FAIL (%s)\n", strerror(errno));
92 	  return (1);
93 	}
94 
95 	puts("PASS");
96       }
97     }
98     else if (!show_oid(fd, community, &(host->addr), argv[i], walk))
99       return (1);
100     else
101       oid = argv[i];
102 
103   if (!host)
104     usage();
105 
106   if (!oid)
107   {
108     if (!show_oid(fd, community,  &(host->addr),
109                   walk ? ".1.3.6.1.2.1.43" :
110 		         ".1.3.6.1.2.1.43.10.2.1.4.1.1", walk))
111       return (1);
112   }
113 
114   return (0);
115 }
116 
117 
118 /*
119  * 'print_packet()' - Print the contents of the response packet.
120  */
121 
122 static void
print_packet(cups_snmp_t * packet,void * data)123 print_packet(cups_snmp_t *packet,	/* I - SNMP response packet */
124              void        *data)		/* I - User data pointer (not used) */
125 {
126   unsigned	i;			/* Looping var */
127   char		temp[1024];		/* Temporary OID string */
128 
129 
130   (void)data;
131 
132   printf("%s = ", _cupsSNMPOIDToString(packet->object_name, temp, sizeof(temp)));
133 
134   switch (packet->object_type)
135   {
136     case CUPS_ASN1_BOOLEAN :
137 	printf("BOOLEAN %s\n",
138 	       packet->object_value.boolean ? "TRUE" : "FALSE");
139 	break;
140 
141     case CUPS_ASN1_INTEGER :
142 	printf("INTEGER %d\n", packet->object_value.integer);
143 	break;
144 
145     case CUPS_ASN1_BIT_STRING :
146 	printf("BIT-STRING \"%s\"\n",
147 	       (char *)packet->object_value.string.bytes);
148 	break;
149 
150     case CUPS_ASN1_OCTET_STRING :
151 	printf("OCTET-STRING \"%s\"\n",
152 	       (char *)packet->object_value.string.bytes);
153 	break;
154 
155     case CUPS_ASN1_NULL_VALUE :
156 	puts("NULL-VALUE");
157 	break;
158 
159     case CUPS_ASN1_OID :
160 	printf("OID %s\n", _cupsSNMPOIDToString(packet->object_value.oid,
161 	                                        temp, sizeof(temp)));
162 	break;
163 
164     case CUPS_ASN1_HEX_STRING :
165 	fputs("Hex-STRING", stdout);
166 	for (i = 0; i < packet->object_value.string.num_bytes; i ++)
167 	  printf(" %02X", packet->object_value.string.bytes[i]);
168 	putchar('\n');
169 	break;
170 
171     case CUPS_ASN1_COUNTER :
172 	printf("Counter %d\n", packet->object_value.counter);
173 	break;
174 
175     case CUPS_ASN1_GAUGE :
176 	printf("Gauge %u\n", packet->object_value.gauge);
177 	break;
178 
179     case CUPS_ASN1_TIMETICKS :
180 	printf("Timeticks %u days, %u:%02u:%02u.%02u\n",
181 	       packet->object_value.timeticks / 8640000,
182 	       (packet->object_value.timeticks / 360000) % 24,
183 	       (packet->object_value.timeticks / 6000) % 60,
184 	       (packet->object_value.timeticks / 100) % 60,
185 	       packet->object_value.timeticks % 100);
186 	break;
187 
188     default :
189 	printf("Unknown-%X\n", packet->object_type);
190 	break;
191   }
192 }
193 
194 
195 /*
196  * 'show_oid()' - Show the specified OID.
197  */
198 
199 static int				/* O - 1 on success, 0 on error */
show_oid(int fd,const char * community,http_addr_t * addr,const char * s,int walk)200 show_oid(int         fd,		/* I - SNMP socket */
201          const char  *community,	/* I - Community name */
202 	 http_addr_t *addr,		/* I - Address to query */
203          const char  *s,		/* I - OID to query */
204 	 int         walk)		/* I - Walk OIDs? */
205 {
206   int		i;			/* Looping var */
207   int		oid[CUPS_SNMP_MAX_OID];	/* OID */
208   cups_snmp_t	packet;			/* SNMP packet */
209   char		temp[1024];		/* Temporary OID string */
210 
211 
212   if (!_cupsSNMPStringToOID(s, oid, sizeof(oid) / sizeof(oid[0])))
213   {
214     puts("testsnmp: Bad OID");
215     return (0);
216   }
217 
218   if (walk)
219   {
220     printf("_cupsSNMPWalk(%s): ", _cupsSNMPOIDToString(oid, temp, sizeof(temp)));
221 
222     if (_cupsSNMPWalk(fd, addr, CUPS_SNMP_VERSION_1, community, oid, 5.0,
223                      print_packet, NULL) < 0)
224     {
225       printf("FAIL (%s)\n", strerror(errno));
226       return (0);
227     }
228   }
229   else
230   {
231     printf("_cupsSNMPWrite(%s): ", _cupsSNMPOIDToString(oid, temp, sizeof(temp)));
232 
233     if (!_cupsSNMPWrite(fd, addr, CUPS_SNMP_VERSION_1, community,
234 		       CUPS_ASN1_GET_REQUEST, 1, oid))
235     {
236       printf("FAIL (%s)\n", strerror(errno));
237       return (0);
238     }
239 
240     puts("PASS");
241 
242     fputs("_cupsSNMPRead(5.0): ", stdout);
243 
244     if (!_cupsSNMPRead(fd, &packet, 5.0))
245     {
246       puts("FAIL (timeout)");
247       return (0);
248     }
249 
250     if (!_cupsSNMPIsOID(&packet, oid))
251     {
252       printf("FAIL (bad OID %d", packet.object_name[0]);
253       for (i = 1; packet.object_name[i] >= 0; i ++)
254 	printf(".%d", packet.object_name[i]);
255       puts(")");
256       return (0);
257     }
258 
259     if (packet.error)
260     {
261       printf("FAIL (%s)\n", packet.error);
262       return (0);
263     }
264 
265     puts("PASS");
266 
267     print_packet(&packet, NULL);
268   }
269 
270   return (1);
271 }
272 
273 
274 /*
275  * 'usage()' - Show program usage and exit.
276  */
277 
278 static void
usage(void)279 usage(void)
280 {
281   puts("Usage: testsnmp [options] host-or-ip [oid ...]");
282   puts("");
283   puts("Options:");
284   puts("");
285   puts("  -c community    Set community name");
286   puts("  -d              Enable debugging");
287   puts("  -w              Walk all OIDs under the specified one");
288 
289   exit (1);
290 }
291