xref: /titanic_52/usr/src/cmd/hal/addons/network-devices/snmp.c (revision eb1d81f3a9f8d0c56b7fca4667287a099fa49cfa)
14e9cfc9aSjacobs /*
2*eb1d81f3SLin Guo - Sun Microsystems  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
34e9cfc9aSjacobs  * Use is subject to license terms.
44e9cfc9aSjacobs  *
54e9cfc9aSjacobs  * Licensed under the Academic Free License version 2.1
64e9cfc9aSjacobs  */
74e9cfc9aSjacobs 
84e9cfc9aSjacobs #include <sys/types.h>
94e9cfc9aSjacobs #include <sys/socket.h>
104e9cfc9aSjacobs #include <netinet/in.h>
114e9cfc9aSjacobs #include <arpa/inet.h>
124e9cfc9aSjacobs 
134e9cfc9aSjacobs #include <glib.h>
144e9cfc9aSjacobs 
154e9cfc9aSjacobs #include <libhal.h>
164e9cfc9aSjacobs #include <logger.h>
174e9cfc9aSjacobs 
184e9cfc9aSjacobs #undef PACKAGE_STRING
194e9cfc9aSjacobs #undef PACKAGE_VERSION
204e9cfc9aSjacobs 
214e9cfc9aSjacobs #include <net-snmp/net-snmp-config.h>
224e9cfc9aSjacobs #include <net-snmp/net-snmp-includes.h>
234e9cfc9aSjacobs 
244e9cfc9aSjacobs #include "network-discovery.h"
254e9cfc9aSjacobs #include "printer.h"
264e9cfc9aSjacobs 
274e9cfc9aSjacobs #define	NP(x)	(x?x:"NULL")
284e9cfc9aSjacobs 
294e9cfc9aSjacobs static GList *new_addrs = NULL;
304e9cfc9aSjacobs 
314e9cfc9aSjacobs static void
324e9cfc9aSjacobs add_snmp_device(LibHalContext *ctx, char *parent, char *name, char *community)
334e9cfc9aSjacobs {
344e9cfc9aSjacobs 	/* most printers listen on the appsocket port (9100) */
354e9cfc9aSjacobs 	if (is_listening(name, 9100) == 0) {
364e9cfc9aSjacobs 		char device[128];
374e9cfc9aSjacobs 
384e9cfc9aSjacobs 		snprintf(device, sizeof (device), "socket://%s:9100", name);
394e9cfc9aSjacobs 
404e9cfc9aSjacobs 		add_network_printer(ctx, parent, name, device, community);
414e9cfc9aSjacobs 	}
424e9cfc9aSjacobs 
434e9cfc9aSjacobs 	/*
444e9cfc9aSjacobs 	 * This would be a good place to detect other types of devices or other
454e9cfc9aSjacobs 	 * device capabilities.  scanners, removable media, storage, ...
464e9cfc9aSjacobs 	 */
474e9cfc9aSjacobs }
484e9cfc9aSjacobs 
494e9cfc9aSjacobs static int
504e9cfc9aSjacobs snmp_response_cb(int operation, struct snmp_session *sp, int reqid,
514e9cfc9aSjacobs 		struct snmp_pdu *pdu, void *data)
524e9cfc9aSjacobs {
534e9cfc9aSjacobs 	struct sockaddr_in *addr = pdu->transport_data;
544e9cfc9aSjacobs 	char *name;
554e9cfc9aSjacobs 
564e9cfc9aSjacobs 	name = inet_ntoa(addr->sin_addr);
574e9cfc9aSjacobs 
584e9cfc9aSjacobs 	/* have we already seen this network device */
594e9cfc9aSjacobs 	if (device_seen(name) == FALSE)
604e9cfc9aSjacobs 		new_addrs = g_list_append(new_addrs, strdup(name));
614e9cfc9aSjacobs 
624e9cfc9aSjacobs 	return (0);
634e9cfc9aSjacobs }
644e9cfc9aSjacobs 
654e9cfc9aSjacobs gboolean
664e9cfc9aSjacobs scan_for_devices_using_snmp(LibHalContext *ctx, char *parent, char *community,
674e9cfc9aSjacobs 		char *network)
684e9cfc9aSjacobs {
694e9cfc9aSjacobs 	struct snmp_session session, *ss;
704e9cfc9aSjacobs 	struct snmp_pdu *request = NULL, *response = NULL;
714e9cfc9aSjacobs 	oid Oid[MAX_OID_LEN];
724e9cfc9aSjacobs 	unsigned int oid_len = MAX_OID_LEN;
734e9cfc9aSjacobs 	GList *elem;
744e9cfc9aSjacobs 
754e9cfc9aSjacobs 	HAL_DEBUG(("scan_for_devices_using_snmp(0x%8.8x, %s, %s, %s)",
764e9cfc9aSjacobs 	    ctx, NP(parent), NP(community), NP(network)));
774e9cfc9aSjacobs 
784e9cfc9aSjacobs 	init_snmp("snmp-scan");
794e9cfc9aSjacobs 	init_mib();
804e9cfc9aSjacobs 
814e9cfc9aSjacobs 	/* initialize the SNMP session */
824e9cfc9aSjacobs 	snmp_sess_init(&session);
834e9cfc9aSjacobs 	session.peername = network;
844e9cfc9aSjacobs 	session.community = (uchar_t *)community;
854e9cfc9aSjacobs 	session.community_len = strlen((const char *)session.community);
864e9cfc9aSjacobs 	session.version = SNMP_VERSION_1;
874e9cfc9aSjacobs 
884e9cfc9aSjacobs 	if ((ss = snmp_open(&session)) == NULL)
894e9cfc9aSjacobs 		return (FALSE);
904e9cfc9aSjacobs 
914e9cfc9aSjacobs 	/* initialize the request PDU */
924e9cfc9aSjacobs 	request = snmp_pdu_create(SNMP_MSG_GET);
934e9cfc9aSjacobs 
944e9cfc9aSjacobs 	/* add the requested data (everyone should have a sysDescr.0) */
954e9cfc9aSjacobs 	if (!read_objid("SNMPv2-MIB::sysDescr.0", Oid, &oid_len))
964e9cfc9aSjacobs 		snmp_perror("sysDescr.0");
974e9cfc9aSjacobs 	snmp_add_null_var(request, Oid, oid_len);
984e9cfc9aSjacobs 
994e9cfc9aSjacobs 	snmp_async_send(ss, request, snmp_response_cb, NULL);
1004e9cfc9aSjacobs 
1014e9cfc9aSjacobs 	/* detect any new devices */
1024e9cfc9aSjacobs 	while (1) {
1034e9cfc9aSjacobs 		int fds = 0, block = 0;
1044e9cfc9aSjacobs 		fd_set fdset;
1054e9cfc9aSjacobs 		struct timeval timeout;
1064e9cfc9aSjacobs 
1074e9cfc9aSjacobs 		FD_ZERO(&fdset);
1084e9cfc9aSjacobs 		snmp_select_info(&fds, &fdset, &timeout, &block);
1094e9cfc9aSjacobs 		fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout);
1104e9cfc9aSjacobs 		if (fds < 0) {
1114e9cfc9aSjacobs 			perror("select failed");
112*eb1d81f3SLin Guo - Sun Microsystems 			break;
1134e9cfc9aSjacobs 		} if (fds == 0) {
1144e9cfc9aSjacobs 			break;
1154e9cfc9aSjacobs 		} else {
1164e9cfc9aSjacobs 			snmp_read(&fdset);
1174e9cfc9aSjacobs 		}
1184e9cfc9aSjacobs 	}
1194e9cfc9aSjacobs 
1204e9cfc9aSjacobs 	snmp_close(ss);
1214e9cfc9aSjacobs 
1224e9cfc9aSjacobs 	/* add the newly detected devices */
1234e9cfc9aSjacobs 	for (elem = new_addrs; elem != NULL; elem = g_list_next(elem)) {
1244e9cfc9aSjacobs 		add_snmp_device(ctx, parent, (char *)elem->data, community);
1254e9cfc9aSjacobs 		free(elem->data);
1264e9cfc9aSjacobs 	}
1274e9cfc9aSjacobs 	g_list_free(new_addrs);
1284e9cfc9aSjacobs 	new_addrs = NULL;
1294e9cfc9aSjacobs 
1304e9cfc9aSjacobs 	return (TRUE);
1314e9cfc9aSjacobs }
132