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