1/*
2 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 *
5 * Licensed under the Academic Free License version 2.1
6 */
7
8#pragma ident	"%Z%%M%	%I%	%E% SMI"
9
10#include <sys/types.h>
11#include <sys/socket.h>
12#include <netinet/in.h>
13#include <arpa/inet.h>
14#include <strings.h>
15
16#undef PACKAGE_STRING
17#undef PACKAGE_VERSION
18
19#include <net-snmp/net-snmp-config.h>
20#include <net-snmp/net-snmp-includes.h>
21
22#include "logger.h"
23#include "printer.h"
24
25static int
26hrDeviceDesc_to_info(char *string, char **manufacturer, char **model,
27		char **description)
28{
29	int rc = -1;
30	char *s;
31
32	if (string == NULL)
33		return (-1);
34
35	/* if it has : and ; in it, it's probably a 1284 device id */
36	if ((strchr(string, ':') != NULL) && (strchr(string, ';') != NULL)) {
37		rc = ieee1284_devid_to_printer_info(string, manufacturer, model,
38				description, NULL, NULL, NULL);
39	} else {
40		rc = 0;
41		*description = strdup(string);
42		*manufacturer = strdup(string);
43		if ((s = strchr(*manufacturer, ' ')) != NULL) {
44			*s++ = NULL;
45			*model = strdup(s);
46		}
47	}
48
49	return (rc);
50}
51
52static struct snmp_pdu *
53snmp_get_item(char *host, char *community, char *mib_item)
54{
55	int status;
56	struct snmp_session session, *ss;
57	struct snmp_pdu *request = NULL, *result = NULL;
58	oid Oid[MAX_OID_LEN];
59	unsigned int oid_len = MAX_OID_LEN;
60
61	/* initialize the SNMP session */
62	snmp_sess_init(&session);
63	session.peername = host;
64	session.community = (uchar_t *)community;
65	session.community_len = strlen((const char *)session.community);
66	session.version = SNMP_VERSION_1;
67	session.retries = 0;
68
69	if ((ss = snmp_open(&session)) == NULL)
70		return (NULL);
71
72	/* add the requested data */
73	if (!read_objid(mib_item, Oid, &oid_len))
74		snmp_perror(mib_item);
75
76	/* initialize the request PDU */
77	request = snmp_pdu_create(SNMP_MSG_GET);
78	snmp_add_null_var(request, Oid, oid_len);
79
80	status = snmp_synch_response(ss, request, &result);
81
82	snmp_close(ss);
83
84	return (result);
85}
86
87static char *
88snmp_get_string(char *host, char *community, char *mib_item)
89{
90	char *result = NULL;
91	struct snmp_pdu *response = NULL;
92
93	response = snmp_get_item(host, community, mib_item);
94
95	if ((response != NULL) && (response->errstat == SNMP_ERR_NOERROR)) {
96		struct variable_list *v = response->variables;
97
98		if (v->type == ASN_OCTET_STR) {
99			result = calloc(1, v->val_len + 1);
100			memcpy(result, v->val.string, v->val_len);
101		}
102	}
103
104	HAL_DEBUG(("snmp_get_string(%s, %s, %s): %s", host, community, mib_item,
105		(result?result:"NULL")));
106
107	if (response != NULL)
108		snmp_free_pdu(response);
109
110	return (result);
111}
112
113static int
114snmp_brother_printer_info(char *hostname, char *community, char **manufacturer,
115		char **model, char **description, char **serial_no,
116		char ***command_set)
117{
118	int rc = -1;
119	char *tmp = NULL;
120
121	/*
122	 * Brother printers appear to store
123	 *	1284 DevID	SNMPv2-SMI::enterprises.2435.2.3.9.1.1.7.0
124	 *	Serial Number	SNMPv2-SMI::enterprises.2435.2.3.9.4.2.1.5.5.1.0
125	 */
126	tmp = snmp_get_string(hostname, community,
127			"SNMPv2-SMI::enterprises.2435.2.3.9.1.1.7.0");
128	if (tmp != NULL) {
129		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
130				description, NULL, serial_no, command_set);
131		free(tmp);
132
133		if (*serial_no == NULL)
134			*serial_no = snmp_get_string(hostname, community,
135				"SNMPv2-SMI::enterprises.2435.2.3.9.4.2.1.5.5.1.0");
136	}
137
138	return (rc);
139}
140
141static int
142snmp_ricoh_printer_info(char *hostname, char *community, char **manufacturer,
143		char **model, char **description, char **serial_no,
144		char ***command_set)
145{
146	int rc = -1;
147	char *tmp = NULL;
148
149	/*
150	 * OKI printers appear to store
151	 *	1284 DevID	SNMPv2-SMI::enterprises.367.3.2.1.1.1.11.0
152	 *	Serial Number	SNMPv2-SMI::enterprises.367.3.2.1.2.1.4.0
153	 */
154	tmp = snmp_get_string(hostname, community,
155			"SNMPv2-SMI::enterprises.367.3.2.1.1.1.11.0");
156	if (tmp != NULL) {
157		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
158				description, NULL, serial_no, command_set);
159		free(tmp);
160
161		if (*serial_no == NULL)
162			*serial_no = snmp_get_string(hostname, community,
163				"SNMPv2-SMI::enterprises.367.3.2.1.2.1.4.0");
164	}
165
166	return (rc);
167}
168
169static int
170snmp_lexmark_printer_info(char *hostname, char *community, char **manufacturer,
171		char **model, char **description, char **serial_no,
172		char ***command_set)
173{
174	int rc = -1;
175	char *tmp = NULL;
176
177	/*
178	 * Lexmark printers appear to store
179	 *	1284 DevID	SNMPv2-SMI::enterprises.641.2.1.2.1.3.1
180	 *	Serial Number	SNMPv2-SMI::enterprises.641.2.1.2.1.6.1
181	 */
182	tmp = snmp_get_string(hostname, community,
183			"SNMPv2-SMI::enterprises.641.2.1.2.1.3.1");
184	if (tmp != NULL) {
185		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
186				description, NULL, serial_no, command_set);
187		free(tmp);
188
189		if (*serial_no == NULL)
190			*serial_no = snmp_get_string(hostname, community,
191				"SNMPv2-SMI::enterprises.641.2.1.2.1.6.1");
192	}
193
194	return (rc);
195}
196
197static int
198snmp_xerox_phaser_printer_info(char *hostname, char *community,
199		char **manufacturer, char **model, char **description,
200		char **serial_no, char ***command_set, char **uri)
201{
202	int rc = -1;
203	char *tmp = NULL;
204
205	/*
206	 * Xerox Phaser XXXX printers store their
207	 *	1284 DevID	SNMPv2-SMI::enterprises.253.8.51.1.2.1.20.1
208	 *	Manufacturer:
209	 *			SNMPv2-SMI::enterprises.128.2.1.3.1.1.0
210	 *			SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.16
211	 *			SNMPv2-SMI::enterprises.23.2.32.4.1.0
212	 *	Model:
213	 *			SNMPv2-SMI::enterprises.128.2.1.3.1.2.0
214	 *			SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.17
215	 *			SNMPv2-SMI::enterprises.23.2.32.4.2.0
216	 *	Description	SNMPv2-SMI::enterprises.253.8.53.3.2.1.2.1
217	 *	Serial Number	SNMPv2-SMI::enterprises.253.8.53.3.2.1.3.1
218	 *	Uri		SNMPv2-SMI::enterprises.128.2.1.3.6.23.1.5.1
219	 */
220
221	tmp = snmp_get_string(hostname, community,
222			"SNMPv2-SMI::enterprises.253.8.51.1.2.1.20.1");
223	if (tmp != NULL) {
224		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
225				description, NULL, serial_no, command_set);
226		free(tmp);
227	}
228
229	if (*manufacturer == NULL)
230		*manufacturer = snmp_get_string(hostname, community,
231			"SNMPv2-SMI::enterprises.128.2.1.3.1.1.0");
232	if (*manufacturer == NULL)
233		*manufacturer = snmp_get_string(hostname, community,
234			"SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.16");
235	if (*manufacturer == NULL)
236		*manufacturer = snmp_get_string(hostname, community,
237			"SNMPv2-SMI::enterprises.23.2.32.4.1.0");
238
239	if (*model == NULL)
240		*model = snmp_get_string(hostname, community,
241			"SNMPv2-SMI::enterprises.128.2.1.3.1.2.0");
242	if (*model == NULL)
243		*model = snmp_get_string(hostname, community,
244			"SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.17");
245	if (*model == NULL)
246		*model = snmp_get_string(hostname, community,
247			"SNMPv2-SMI::enterprises.23.2.32.4.2.0");
248
249	if (*serial_no == NULL)
250		*serial_no = snmp_get_string(hostname, community,
251			"SNMPv2-SMI::enterprises.253.8.53.3.2.1.3.1");
252
253	if ((*manufacturer != NULL) && (*model != NULL))
254		rc = 0;
255
256	return (rc);
257}
258
259static int
260snmp_qms_printer_info(char *hostname, char *community, char **manufacturer,
261		char **model, char **description, char **serial_no,
262		char ***command_set, char **uri)
263{
264	int rc = -1;
265	char *tmp = NULL;
266
267	/*
268	 * MINOLTA-QMS printers appear to store
269	 *	Prouct Name	SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.1.1.16.1
270	 *	Serial Number	SNMPv2-SMI::enterprises.2590.1.1.1.5.5.1.1.3.2
271	 *	URI		SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.1
272	 *			SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.2
273	 */
274	tmp = snmp_get_string(hostname, community,
275		"SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.1.1.16.1");
276	if (tmp != NULL) {
277		rc = hrDeviceDesc_to_info(tmp, manufacturer, model,
278					description);
279		free(tmp);
280
281		if (*serial_no == NULL)
282			*serial_no = snmp_get_string(hostname, community,
283				"SNMPv2-SMI::enterprises.2590.1.1.1.5.5.1.1.3.2");
284		tmp = snmp_get_string(hostname, community,
285			"SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.2");
286		if (tmp == NULL)
287			tmp = snmp_get_string(hostname, community,
288				"SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.1");
289		if (tmp != NULL)
290			*uri = tmp;
291	}
292
293	return (rc);
294}
295
296static int
297snmp_oki_printer_info(char *hostname, char *community, char **manufacturer,
298		char **model, char **description, char **serial_no,
299		char ***command_set)
300{
301	int rc = -1;
302	char *tmp = NULL;
303
304	/*
305	 * OKI printers appear to store
306	 *	Prouct Name	SNMPv2-SMI::enterprises.2001.1.2.683.1.3
307	 *	Serial Number	SNMPv2-SMI::enterprises.2001.1.2.683.1.5
308	 */
309	tmp = snmp_get_string(hostname, community,
310			"SNMPv2-SMI::enterprises.2001.1.2.683.1.3");
311	if (tmp != NULL) {
312		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
313				description, NULL, serial_no, command_set);
314		free(tmp);
315
316		if (*serial_no == NULL)
317			*serial_no = snmp_get_string(hostname, community,
318				"SNMPv2-SMI::enterprises.2001.1.2.683.1.5");
319	}
320
321	return (rc);
322}
323
324static int
325snmp_hp_printer_info(char *hostname, char *community, char **manufacturer,
326		char **model, char **description, char **serial_no,
327		char ***command_set)
328{
329	int rc = -1;
330	char *tmp = NULL;
331
332	/*
333	 * HP printers appear to store
334	 *	1284 DevID	SNMPv2-SMI::enterprises.11.2.3.9.1.1.7.0
335	 *	Serial Number	SNMPv2-SMI::enterprises.2.3.9.4.2.2.5.1.1.17
336	 */
337	tmp = snmp_get_string(hostname, community,
338			"SNMPv2-SMI::enterprises.11.2.3.9.1.1.7.0");
339	if (tmp != NULL) {
340		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
341				description, NULL, serial_no, command_set);
342		free(tmp);
343
344		if (*serial_no == NULL)
345			*serial_no = snmp_get_string(hostname, community,
346				"SNMPv2-SMI::enterprises.2.3.9.4.2.2.5.1.1.17");
347	}
348
349	return (rc);
350}
351
352static int
353snmp_ppm_printer_info(char *hostname, char *community, char **manufacturer,
354		char **model, char **description, char **serial_no,
355		char ***command_set)
356{
357	int rc = -1;
358	char *tmp = NULL;
359
360	/*
361	 * The PWG portMon MIB stores
362	 *	1284 DevID	SNMPv2-SMI::enterprises.2699.1.2.1.1.1.3`
363	 */
364	tmp = snmp_get_string(hostname, community,
365			"SNMPv2-SMI::enterprises.2699.1.2.1.1.1.3");
366	if (tmp != NULL) {
367		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
368				description, NULL, serial_no, command_set);
369		free(tmp);
370	}
371
372	return (rc);
373}
374
375static int
376snmp_prt_printer_info(char *hostname, char *community, char **manufacturer,
377		char **model, char **description, char **serial_no,
378		char ***command_set)
379{
380	int rc = -1;
381	char *tmp = NULL;
382
383	/*
384	 * The Printer Printer MIB stores
385	 *	Vendor	 SNMPv2-SMI::mib-2.43.8.2.1.14.1.1
386	 *	Model	 SNMPv2-SMI::mib-2.43.8.2.1.15.1.1
387	 *	Serial	 SNMPv2-SMI::mib-2.43.8.2.1.17.1.1
388	 */
389
390	if (*manufacturer == NULL)
391		*manufacturer = snmp_get_string(hostname, community,
392				"SNMPv2-SMI::mib-2.43.8.2.1.14.1.1");
393	if (*model == NULL)
394		*model = snmp_get_string(hostname, community,
395				"SNMPv2-SMI::mib-2.43.8.2.1.15.1.1");
396	if (*serial_no == NULL)
397		*serial_no = snmp_get_string(hostname, community,
398				"SNMPv2-SMI::mib-2.43.8.2.1.17.1.1");
399
400	if (*manufacturer != NULL)
401		rc = 0;
402
403	return (rc);
404}
405
406static int
407snmp_host_resource_printer_info(char *hostname, char *community,
408		char **manufacturer, char **model, char **description,
409		char **serial_no, char ***command_set)
410{
411	int rc = -1;
412	char *tmp = NULL;
413
414	tmp = snmp_get_string(hostname, community,
415			"HOST-RESOURCES-MIB::hrDeviceDescr.1");
416	if (tmp != NULL) {
417		rc = hrDeviceDesc_to_info(tmp, manufacturer, model,
418					description);
419		free(tmp);
420	}
421
422	return (rc);
423}
424
425int
426snmp_printer_info(char *hostname, char *community, char **manufacturer,
427		char **model, char **description, char **serial_no,
428		char ***command_set, char **uri)
429{
430	char *tmp = NULL;
431
432	init_snmp("network-printer-probe");
433	init_mib();
434
435	if (snmp_brother_printer_info(hostname, community, manufacturer, model,
436			description, serial_no, command_set) == 0) {
437		return (0);
438	} else if (snmp_ricoh_printer_info(hostname, community, manufacturer,
439			model, description, serial_no, command_set) == 0) {
440		return (0);
441	} else if (snmp_lexmark_printer_info(hostname, community, manufacturer,
442			model, description, serial_no, command_set) == 0) {
443		return (0);
444	} else if (snmp_xerox_phaser_printer_info(hostname, community,
445			manufacturer, model, description, serial_no,
446			command_set, uri) == 0) {
447		return (0);
448	} else if (snmp_qms_printer_info(hostname, community, manufacturer,
449			model, description, serial_no, command_set, uri) == 0) {
450		return (0);
451	} else if (snmp_oki_printer_info(hostname, community, manufacturer,
452			model, description, serial_no, command_set) == 0) {
453		return (0);
454	} else if (snmp_hp_printer_info(hostname, community, manufacturer,
455			model, description, serial_no, command_set) == 0) {
456		return (0);
457	} else if (snmp_ppm_printer_info(hostname, community, manufacturer,
458			model, description, serial_no, command_set) == 0) {
459		return (0);
460	} else if (snmp_prt_printer_info(hostname, community, manufacturer,
461			model, description, serial_no, command_set) == 0) {
462		return (0);
463	} else if (snmp_host_resource_printer_info(hostname, community,
464			manufacturer, model, description, serial_no,
465			command_set) == 0) {
466		return (0);
467	}
468
469	return (-1);
470}
471
472#ifdef NOTDEF
473
474#define	NP(x)	(x?x:"")
475
476int
477main(int ac, char *av[])
478{
479	int i;
480
481	for (i = 1; av[i] != NULL; i++) {
482		char *hostname = av[i], *manufacturer = NULL, *model = NULL,
483		     *description = NULL, *serial_no = NULL,
484		     **command_set = NULL, *uri = NULL;
485		int rc;
486
487		rc = snmp_printer_info(hostname, &manufacturer, &model,
488				&description, &serial_no, &command_set, &uri);
489		printf("SNMP data for %s...(%d)\n", hostname, rc);
490		printf("\tvendor = %s\n", NP(manufacturer));
491		printf("\tproduct = %s\n", NP(model));
492		printf("\tdescription = %s\n", NP(description));
493		printf("\tserial = %s\n", NP(serial_no));
494		printf("\tdevice = %s\n", NP(uri));
495
496		if (command_set != NULL) {
497			int j;
498
499			printf("\tcommand set = \n");
500			for (j = 0; command_set[j] != NULL; j++)
501				printf("\t\t%s\n", command_set[j]);
502		}
503	}
504
505	return (0);
506}
507#endif
508