4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs/*
eb1d81f3a9f8d0c56b7fca4667287a099fa49cfaLin Guo - Sun Microsystems * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs * Use is subject to license terms.
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs *
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs * Licensed under the Academic Free License version 2.1
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <sys/types.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <sys/socket.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <netinet/in.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <arpa/inet.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <glib.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <libhal.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <logger.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#undef PACKAGE_STRING
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#undef PACKAGE_VERSION
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <net-snmp/net-snmp-config.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include <net-snmp/net-snmp-includes.h>
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include "network-discovery.h"
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs#include "printer.h"
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
eb1d81f3a9f8d0c56b7fca4667287a099fa49cfaLin Guo - Sun Microsystems#define NP(x) (x?x:"NULL")
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobsstatic GList *new_addrs = NULL;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobsstatic void
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobsadd_snmp_device(LibHalContext *ctx, char *parent, char *name, char *community)
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs{
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /* most printers listen on the appsocket port (9100) */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs if (is_listening(name, 9100) == 0) {
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs char device[128];
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snprintf(device, sizeof (device), "socket://%s:9100", name);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs add_network_printer(ctx, parent, name, device, community);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs }
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /*
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs * This would be a good place to detect other types of devices or other
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs * device capabilities. scanners, removable media, storage, ...
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs}
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobsstatic int
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobssnmp_response_cb(int operation, struct snmp_session *sp, int reqid,
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs struct snmp_pdu *pdu, void *data)
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs{
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs struct sockaddr_in *addr = pdu->transport_data;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs char *name;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs name = inet_ntoa(addr->sin_addr);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /* have we already seen this network device */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs if (device_seen(name) == FALSE)
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs new_addrs = g_list_append(new_addrs, strdup(name));
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs return (0);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs}
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobsgboolean
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobsscan_for_devices_using_snmp(LibHalContext *ctx, char *parent, char *community,
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs char *network)
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs{
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs struct snmp_session session, *ss;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs struct snmp_pdu *request = NULL, *response = NULL;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs oid Oid[MAX_OID_LEN];
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs unsigned int oid_len = MAX_OID_LEN;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs GList *elem;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs HAL_DEBUG(("scan_for_devices_using_snmp(0x%8.8x, %s, %s, %s)",
eb1d81f3a9f8d0c56b7fca4667287a099fa49cfaLin Guo - Sun Microsystems ctx, NP(parent), NP(community), NP(network)));
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs init_snmp("snmp-scan");
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs init_mib();
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /* initialize the SNMP session */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snmp_sess_init(&session);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs session.peername = network;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs session.community = (uchar_t *)community;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs session.community_len = strlen((const char *)session.community);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs session.version = SNMP_VERSION_1;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs if ((ss = snmp_open(&session)) == NULL)
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs return (FALSE);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /* initialize the request PDU */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs request = snmp_pdu_create(SNMP_MSG_GET);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /* add the requested data (everyone should have a sysDescr.0) */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs if (!read_objid("SNMPv2-MIB::sysDescr.0", Oid, &oid_len))
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snmp_perror("sysDescr.0");
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snmp_add_null_var(request, Oid, oid_len);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snmp_async_send(ss, request, snmp_response_cb, NULL);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /* detect any new devices */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs while (1) {
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs int fds = 0, block = 0;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs fd_set fdset;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs struct timeval timeout;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs FD_ZERO(&fdset);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snmp_select_info(&fds, &fdset, &timeout, &block);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs if (fds < 0) {
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs perror("select failed");
eb1d81f3a9f8d0c56b7fca4667287a099fa49cfaLin Guo - Sun Microsystems break;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs } if (fds == 0) {
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs break;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs } else {
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snmp_read(&fdset);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs }
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs }
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs snmp_close(ss);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs /* add the newly detected devices */
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs for (elem = new_addrs; elem != NULL; elem = g_list_next(elem)) {
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs add_snmp_device(ctx, parent, (char *)elem->data, community);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs free(elem->data);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs }
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs g_list_free(new_addrs);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs new_addrs = NULL;
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs return (TRUE);
4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3jacobs}