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