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