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