xref: /onnv-gate/usr/src/cmd/hal/addons/network-devices/snmp.c (revision 5307:ea4512a0e608)
1*5307Sjacobs /*
2*5307Sjacobs  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3*5307Sjacobs  * Use is subject to license terms.
4*5307Sjacobs  *
5*5307Sjacobs  * Licensed under the Academic Free License version 2.1
6*5307Sjacobs  */
7*5307Sjacobs 
8*5307Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
9*5307Sjacobs 
10*5307Sjacobs #include <sys/types.h>
11*5307Sjacobs #include <sys/socket.h>
12*5307Sjacobs #include <netinet/in.h>
13*5307Sjacobs #include <arpa/inet.h>
14*5307Sjacobs 
15*5307Sjacobs #include <glib.h>
16*5307Sjacobs 
17*5307Sjacobs #include <libhal.h>
18*5307Sjacobs #include <logger.h>
19*5307Sjacobs 
20*5307Sjacobs #undef PACKAGE_STRING
21*5307Sjacobs #undef PACKAGE_VERSION
22*5307Sjacobs 
23*5307Sjacobs #include <net-snmp/net-snmp-config.h>
24*5307Sjacobs #include <net-snmp/net-snmp-includes.h>
25*5307Sjacobs 
26*5307Sjacobs #include "network-discovery.h"
27*5307Sjacobs #include "printer.h"
28*5307Sjacobs 
29*5307Sjacobs #define NP(x)   (x?x:"NULL")
30*5307Sjacobs 
31*5307Sjacobs static GList *new_addrs = NULL;
32*5307Sjacobs 
33*5307Sjacobs static void
34*5307Sjacobs add_snmp_device(LibHalContext *ctx, char *parent, char *name, char *community)
35*5307Sjacobs {
36*5307Sjacobs 	/* most printers listen on the appsocket port (9100) */
37*5307Sjacobs 	if (is_listening(name, 9100) == 0) {
38*5307Sjacobs 		char device[128];
39*5307Sjacobs 
40*5307Sjacobs 		snprintf(device, sizeof (device), "socket://%s:9100", name);
41*5307Sjacobs 
42*5307Sjacobs 		add_network_printer(ctx, parent, name, device, community);
43*5307Sjacobs 	}
44*5307Sjacobs 
45*5307Sjacobs 	/*
46*5307Sjacobs 	 * This would be a good place to detect other types of devices or other
47*5307Sjacobs 	 * device capabilities.  scanners, removable media, storage, ...
48*5307Sjacobs 	 */
49*5307Sjacobs }
50*5307Sjacobs 
51*5307Sjacobs static int
52*5307Sjacobs snmp_response_cb(int operation, struct snmp_session *sp, int reqid,
53*5307Sjacobs 		struct snmp_pdu *pdu, void *data)
54*5307Sjacobs {
55*5307Sjacobs 	struct sockaddr_in *addr = pdu->transport_data;
56*5307Sjacobs 	char *name;
57*5307Sjacobs 
58*5307Sjacobs 	name = inet_ntoa(addr->sin_addr);
59*5307Sjacobs 
60*5307Sjacobs 	/* have we already seen this network device */
61*5307Sjacobs 	if (device_seen(name) == FALSE)
62*5307Sjacobs 		new_addrs = g_list_append(new_addrs, strdup(name));
63*5307Sjacobs 
64*5307Sjacobs 	return (0);
65*5307Sjacobs }
66*5307Sjacobs 
67*5307Sjacobs gboolean
68*5307Sjacobs scan_for_devices_using_snmp(LibHalContext *ctx, char *parent, char *community,
69*5307Sjacobs 		char *network)
70*5307Sjacobs {
71*5307Sjacobs 	struct snmp_session session, *ss;
72*5307Sjacobs 	struct snmp_pdu *request = NULL, *response = NULL;
73*5307Sjacobs 	oid Oid[MAX_OID_LEN];
74*5307Sjacobs 	unsigned int oid_len = MAX_OID_LEN;
75*5307Sjacobs 	GList *elem;
76*5307Sjacobs 
77*5307Sjacobs 	HAL_DEBUG(("scan_for_devices_using_snmp(0x%8.8x, %s, %s, %s)",
78*5307Sjacobs 			ctx, NP(parent), NP(community), NP(network)));
79*5307Sjacobs 
80*5307Sjacobs 	init_snmp("snmp-scan");
81*5307Sjacobs 	init_mib();
82*5307Sjacobs 
83*5307Sjacobs 	/* initialize the SNMP session */
84*5307Sjacobs 	snmp_sess_init(&session);
85*5307Sjacobs 	session.peername = network;
86*5307Sjacobs 	session.community = (uchar_t *)community;
87*5307Sjacobs 	session.community_len = strlen((const char *)session.community);
88*5307Sjacobs 	session.version = SNMP_VERSION_1;
89*5307Sjacobs 
90*5307Sjacobs 	if ((ss = snmp_open(&session)) == NULL)
91*5307Sjacobs 		return (FALSE);
92*5307Sjacobs 
93*5307Sjacobs 	/* initialize the request PDU */
94*5307Sjacobs 	request = snmp_pdu_create(SNMP_MSG_GET);
95*5307Sjacobs 
96*5307Sjacobs 	/* add the requested data (everyone should have a sysDescr.0) */
97*5307Sjacobs 	if (!read_objid("SNMPv2-MIB::sysDescr.0", Oid, &oid_len))
98*5307Sjacobs 		snmp_perror("sysDescr.0");
99*5307Sjacobs 	snmp_add_null_var(request, Oid, oid_len);
100*5307Sjacobs 
101*5307Sjacobs 	snmp_async_send(ss, request, snmp_response_cb, NULL);
102*5307Sjacobs 
103*5307Sjacobs 	/* detect any new devices */
104*5307Sjacobs 	while (1) {
105*5307Sjacobs 		int fds = 0, block = 0;
106*5307Sjacobs 		fd_set fdset;
107*5307Sjacobs 		struct timeval timeout;
108*5307Sjacobs 
109*5307Sjacobs 		FD_ZERO(&fdset);
110*5307Sjacobs 		snmp_select_info(&fds, &fdset, &timeout, &block);
111*5307Sjacobs 		fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout);
112*5307Sjacobs 		if (fds < 0) {
113*5307Sjacobs 			perror("select failed");
114*5307Sjacobs 			continue;
115*5307Sjacobs 		} if (fds == 0) {
116*5307Sjacobs 			break;
117*5307Sjacobs 		} else {
118*5307Sjacobs 			snmp_read(&fdset);
119*5307Sjacobs 		}
120*5307Sjacobs 	}
121*5307Sjacobs 
122*5307Sjacobs 	snmp_close(ss);
123*5307Sjacobs 
124*5307Sjacobs 	/* add the newly detected devices */
125*5307Sjacobs 	for (elem = new_addrs; elem != NULL; elem = g_list_next(elem)) {
126*5307Sjacobs 		add_snmp_device(ctx, parent, (char *)elem->data, community);
127*5307Sjacobs 		free(elem->data);
128*5307Sjacobs 	}
129*5307Sjacobs 	g_list_free(new_addrs);
130*5307Sjacobs 	new_addrs = NULL;
131*5307Sjacobs 
132*5307Sjacobs 	return (TRUE);
133*5307Sjacobs }
134