1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 * 5 * Licensed under the Academic Free License version 2.1 6 */ 7 8 #include <sys/types.h> 9 #include <sys/socket.h> 10 #include <netinet/in.h> 11 #include <arpa/inet.h> 12 13 #include <glib.h> 14 15 #include <libhal.h> 16 #include <logger.h> 17 18 #undef PACKAGE_STRING 19 #undef PACKAGE_VERSION 20 21 #include <net-snmp/net-snmp-config.h> 22 #include <net-snmp/net-snmp-includes.h> 23 24 #include "network-discovery.h" 25 #include "printer.h" 26 27 #define NP(x) (x?x:"NULL") 28 29 static GList *new_addrs = NULL; 30 31 static void 32 add_snmp_device(LibHalContext *ctx, char *parent, char *name, char *community) 33 { 34 /* most printers listen on the appsocket port (9100) */ 35 if (is_listening(name, 9100) == 0) { 36 char device[128]; 37 38 snprintf(device, sizeof (device), "socket://%s:9100", name); 39 40 add_network_printer(ctx, parent, name, device, community); 41 } 42 43 /* 44 * This would be a good place to detect other types of devices or other 45 * device capabilities. scanners, removable media, storage, ... 46 */ 47 } 48 49 static int 50 snmp_response_cb(int operation, struct snmp_session *sp, int reqid, 51 struct snmp_pdu *pdu, void *data) 52 { 53 struct sockaddr_in *addr = pdu->transport_data; 54 char *name; 55 56 name = inet_ntoa(addr->sin_addr); 57 58 /* have we already seen this network device */ 59 if (device_seen(name) == FALSE) 60 new_addrs = g_list_append(new_addrs, strdup(name)); 61 62 return (0); 63 } 64 65 gboolean 66 scan_for_devices_using_snmp(LibHalContext *ctx, char *parent, char *community, 67 char *network) 68 { 69 struct snmp_session session, *ss; 70 struct snmp_pdu *request = NULL, *response = NULL; 71 oid Oid[MAX_OID_LEN]; 72 unsigned int oid_len = MAX_OID_LEN; 73 GList *elem; 74 75 HAL_DEBUG(("scan_for_devices_using_snmp(0x%8.8x, %s, %s, %s)", 76 ctx, NP(parent), NP(community), NP(network))); 77 78 init_snmp("snmp-scan"); 79 init_mib(); 80 81 /* initialize the SNMP session */ 82 snmp_sess_init(&session); 83 session.peername = network; 84 session.community = (uchar_t *)community; 85 session.community_len = strlen((const char *)session.community); 86 session.version = SNMP_VERSION_1; 87 88 if ((ss = snmp_open(&session)) == NULL) 89 return (FALSE); 90 91 /* initialize the request PDU */ 92 request = snmp_pdu_create(SNMP_MSG_GET); 93 94 /* add the requested data (everyone should have a sysDescr.0) */ 95 if (!read_objid("SNMPv2-MIB::sysDescr.0", Oid, &oid_len)) 96 snmp_perror("sysDescr.0"); 97 snmp_add_null_var(request, Oid, oid_len); 98 99 snmp_async_send(ss, request, snmp_response_cb, NULL); 100 101 /* detect any new devices */ 102 while (1) { 103 int fds = 0, block = 0; 104 fd_set fdset; 105 struct timeval timeout; 106 107 FD_ZERO(&fdset); 108 snmp_select_info(&fds, &fdset, &timeout, &block); 109 fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout); 110 if (fds < 0) { 111 perror("select failed"); 112 break; 113 } if (fds == 0) { 114 break; 115 } else { 116 snmp_read(&fdset); 117 } 118 } 119 120 snmp_close(ss); 121 122 /* add the newly detected devices */ 123 for (elem = new_addrs; elem != NULL; elem = g_list_next(elem)) { 124 add_snmp_device(ctx, parent, (char *)elem->data, community); 125 free(elem->data); 126 } 127 g_list_free(new_addrs); 128 new_addrs = NULL; 129 130 return (TRUE); 131 } 132