/*
- * "$Id: snmp.c 6649 2007-07-11 21:46:42Z mike $"
+ * SNMP discovery backend for CUPS.
*
- * SNMP discovery backend for the Common UNIX Printing System (CUPS).
+ * Copyright © 2007-2014 by Apple Inc.
+ * Copyright © 2006-2007 by Easy Software Products, all rights reserved.
*
- * Copyright 2007-2008 by Apple Inc.
- * Copyright 2006-2007 by Easy Software Products, all rights reserved.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * "LICENSE" which should have been included with this file. If this
- * file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- * main() - Discover printers via SNMP.
- * add_array() - Add a string to an array.
- * add_cache() - Add a cached device...
- * add_device_uri() - Add a device URI to the cache.
- * alarm_handler() - Handle alarm signals...
- * compare_cache() - Compare two cache entries.
- * debug_printf() - Display some debugging information.
- * fix_make_model() - Fix common problems in the make-and-model
- * string.
- * free_array() - Free an array of strings.
- * free_cache() - Free the array of cached devices.
- * get_interface_addresses() - Get the broadcast address(es) associated with
- * an interface.
- * list_device() - List a device we found...
- * password_cb() - Handle authentication requests.
- * probe_device() - Probe a device to discover whether it is a
- * printer.
- * read_snmp_conf() - Read the snmp.conf file.
- * read_snmp_response() - Read and parse a SNMP response...
- * run_time() - Return the total running time...
- * scan_devices() - Scan for devices using SNMP.
- * try_connect() - Try connecting on a port...
- * update_cache() - Update a cached device...
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
* Types...
*/
+enum /**** Request IDs for each field ****/
+{
+ DEVICE_TYPE = 1,
+ DEVICE_DESCRIPTION,
+ DEVICE_LOCATION,
+ DEVICE_ID,
+ DEVICE_URI,
+ DEVICE_PRODUCT
+};
+
typedef struct device_uri_s /**** DeviceURI values ****/
{
regex_t re; /* Regular expression to match */
*uri, /* device-uri */
*id, /* device-id */
*info, /* device-info */
+ *location, /* device-location */
*make_and_model; /* device-make-and-model */
+ int sent; /* Has this device been listed? */
} snmp_cache_t;
-/*
- * Private CUPS API to set the last error...
- */
-
-extern void _cupsSetError(ipp_status_t status, const char *message);
-
-
/*
* Local functions...
*/
static void read_snmp_conf(const char *address);
static void read_snmp_response(int fd);
static double run_time(void);
-static void scan_devices(int fd);
+static void scan_devices(int ipv4, int ipv6);
static int try_connect(http_addr_t *addr, const char *addrname,
int port);
static void update_cache(snmp_cache_t *device, const char *uri,
static cups_array_t *Communities = NULL;
static cups_array_t *Devices = NULL;
static int DebugLevel = 0;
-static const int DeviceDescOID[] = { CUPS_OID_hrDeviceDescr, 1, -1 };
-static unsigned DeviceDescRequest;
+static const int DescriptionOID[] = { CUPS_OID_hrDeviceDescr, 1, -1 };
+static const int LocationOID[] = { CUPS_OID_sysLocation, 0, -1 };
static const int DeviceTypeOID[] = { CUPS_OID_hrDeviceType, 1, -1 };
-static unsigned DeviceTypeRequest;
static const int DeviceIdOID[] = { CUPS_OID_ppmPrinterIEEE1284DeviceId, 1, -1 };
-static unsigned DeviceIdRequest;
-static const int DeviceUriOID[] = { CUPS_OID_ppmPortServiceNameOrURI, 1, 1, -1 };
-static unsigned DeviceUriRequest;
+static const int UriOID[] = { CUPS_OID_ppmPortServiceNameOrURI, 1, 1, -1 };
+static const int LexmarkProductOID[] = { 1,3,6,1,4,1,641,2,1,2,1,2,1,-1 };
+static const int LexmarkProductOID2[] = { 1,3,6,1,4,1,674,10898,100,2,1,2,1,2,1,-1 };
+static const int LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 };
+static const int HPDeviceIdOID[] = { 1,3,6,1,4,1,11,2,3,9,1,1,7,0,-1 };
+static const int RicohDeviceIdOID[] = { 1,3,6,1,4,1,367,3,2,1,1,1,11,0,-1 };
+static const int XeroxProductOID[] = { 1,3,6,1,4,1,128,2,1,3,1,2,0,-1 };
static cups_array_t *DeviceURIs = NULL;
static int HostNameLookups = 0;
static int MaxRunTime = 120;
main(int argc, /* I - Number of command-line arguments (6 or 7) */
char *argv[]) /* I - Command-line arguments */
{
- int fd; /* SNMP socket */
+ int ipv4, /* SNMP IPv4 socket */
+ ipv6; /* SNMP IPv6 socket */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
if (argc > 2)
{
- fputs(_("Usage: snmp [host-or-ip-address]\n"), stderr);
+ _cupsLangPuts(stderr, _("Usage: snmp [host-or-ip-address]"));
return (1);
}
* Open the SNMP socket...
*/
- if ((fd = _cupsSNMPOpen(AF_INET)) < 0)
+ if ((ipv4 = _cupsSNMPOpen(AF_INET)) < 0)
return (1);
+#ifdef AF_INET6
+ if ((ipv6 = _cupsSNMPOpen(AF_INET6)) < 0)
+ perror("DEBUG: Unable to create IPv6 socket");
+#else
+ ipv6 = -1;
+#endif /* AF_INET6 */
+
/*
* Read the configuration file and any cache data...
*/
* Scan for devices...
*/
- scan_devices(fd);
+ scan_devices(ipv4, ipv6);
/*
* Close, free, and return with no errors...
*/
- _cupsSNMPClose(fd);
+ _cupsSNMPClose(ipv4);
+ if (ipv6 >= 0)
+ _cupsSNMPClose(ipv6);
free_array(Addresses);
free_array(Communities);
#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
if (DebugLevel)
- write(2, "DEBUG: ALARM!\n", 14);
+ backendMessage("DEBUG: ALARM!\n");
}
compare_cache(snmp_cache_t *a, /* I - First cache entry */
snmp_cache_t *b) /* I - Second cache entry */
{
- return (strcasecmp(a->addrname, b->addrname));
+ return (_cups_strcasecmp(a->addrname, b->addrname));
}
* that printer driver detection works better...
*/
- if (!strncasecmp(old_make_model, "Hewlett-Packard", 15))
+ if (!_cups_strncasecmp(old_make_model, "Hewlett-Packard", 15))
{
/*
* Strip leading Hewlett-Packard and hp prefixes and replace
while (isspace(*mmptr & 255))
mmptr ++;
- if (!strncasecmp(mmptr, "hp", 2))
+ if (!_cups_strncasecmp(mmptr, "hp", 2))
{
mmptr += 2;
make_model[0] = 'H';
make_model[1] = 'P';
make_model[2] = ' ';
- strlcpy(make_model + 3, mmptr, make_model_size - 3);
+ strlcpy(make_model + 3, mmptr, (size_t)make_model_size - 3);
}
- else if (!strncasecmp(old_make_model, "deskjet", 7))
- snprintf(make_model, make_model_size, "HP DeskJet%s", old_make_model + 7);
- else if (!strncasecmp(old_make_model, "officejet", 9))
- snprintf(make_model, make_model_size, "HP OfficeJet%s", old_make_model + 9);
- else if (!strncasecmp(old_make_model, "stylus_pro_", 11))
- snprintf(make_model, make_model_size, "EPSON Stylus Pro %s",
- old_make_model + 11);
+ else if (!_cups_strncasecmp(old_make_model, "deskjet", 7))
+ snprintf(make_model, (size_t)make_model_size, "HP DeskJet%s", old_make_model + 7);
+ else if (!_cups_strncasecmp(old_make_model, "officejet", 9))
+ snprintf(make_model, (size_t)make_model_size, "HP OfficeJet%s", old_make_model + 9);
+ else if (!_cups_strncasecmp(old_make_model, "stylus_pro_", 11))
+ snprintf(make_model, (size_t)make_model_size, "EPSON Stylus Pro %s", old_make_model + 11);
else
- strlcpy(make_model, old_make_model, make_model_size);
+ strlcpy(make_model, old_make_model, (size_t)make_model_size);
if ((mmptr = strstr(make_model, ", Inc.,")) != NULL)
{
list_device(snmp_cache_t *cache) /* I - Cached device */
{
if (cache->uri)
- {
- printf("network %s \"%s\" \"%s %s\" \"%s\"\n",
- cache->uri,
- cache->make_and_model ? cache->make_and_model : "Unknown",
- cache->info ? cache->info : "Unknown",
- cache->addrname,
- cache->id ? cache->id : "");
- fflush(stdout);
- }
+ cupsBackendReport("network", cache->uri, cache->make_and_model,
+ cache->info, cache->id, cache->location);
}
#ifdef __APPLE__
/*
- * TODO: Try an mDNS query first, and then fallback on direct probes...
+ * If the printer supports Bonjour/mDNS, don't report it from the SNMP backend.
*/
if (!try_connect(&(device->address), device->addrname, 5353))
* Insert hostname/address...
*/
- strlcpy(uriptr, device->addrname, sizeof(uri) - (uriptr - uri));
+ strlcpy(uriptr, device->addrname, sizeof(uri) - (size_t)(uriptr - uri));
uriptr += strlen(uriptr);
format += 2;
}
if (!value)
fprintf(stderr, "ERROR: Missing value on line %d of %s!\n", linenum,
filename);
- else if (!strcasecmp(line, "Address"))
+ else if (!_cups_strcasecmp(line, "Address"))
{
if (!address)
add_array(Addresses, value);
}
- else if (!strcasecmp(line, "Community"))
+ else if (!_cups_strcasecmp(line, "Community"))
add_array(Communities, value);
- else if (!strcasecmp(line, "DebugLevel"))
+ else if (!_cups_strcasecmp(line, "DebugLevel"))
DebugLevel = atoi(value);
- else if (!strcasecmp(line, "DeviceURI"))
+ else if (!_cups_strcasecmp(line, "DeviceURI"))
{
if (*value != '\"')
fprintf(stderr,
else
add_device_uri(value);
}
- else if (!strcasecmp(line, "HostNameLookups"))
- HostNameLookups = !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "true") ||
- !strcasecmp(value, "double");
- else if (!strcasecmp(line, "MaxRunTime"))
+ else if (!_cups_strcasecmp(line, "HostNameLookups"))
+ HostNameLookups = !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") ||
+ !_cups_strcasecmp(value, "true") ||
+ !_cups_strcasecmp(value, "double");
+ else if (!_cups_strcasecmp(line, "MaxRunTime"))
MaxRunTime = atoi(value);
else
fprintf(stderr, "ERROR: Unknown directive %s on line %d of %s!\n",
debug_printf("DEBUG: request-id=%d\n", packet.request_id);
debug_printf("DEBUG: error-status=%d\n", packet.error_status);
- if (packet.error_status)
+ if (packet.error_status && packet.request_id != DEVICE_TYPE)
return;
/*
* Process the message...
*/
- if (packet.request_id == DeviceTypeRequest)
+ switch (packet.request_id)
{
- /*
- * Got the device type response...
- */
-
- if (device)
- {
- debug_printf("DEBUG: Discarding duplicate device type for \"%s\"...\n",
- addrname);
- return;
- }
-
- /*
- * Add the device and request the device description...
- */
-
- add_cache(&(packet.address), addrname, NULL, NULL, NULL);
-
- _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community,
- CUPS_ASN1_GET_REQUEST, DeviceDescRequest, DeviceDescOID);
- _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community,
- CUPS_ASN1_GET_REQUEST, DeviceIdRequest, DeviceIdOID);
- _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community,
- CUPS_ASN1_GET_REQUEST, DeviceUriRequest, DeviceUriOID);
- }
- else if (packet.request_id == DeviceDescRequest &&
- packet.object_type == CUPS_ASN1_OCTET_STRING)
- {
- /*
- * Update an existing cache entry...
- */
-
- char make_model[256]; /* Make and model */
-
-
- if (!device)
- {
- debug_printf("DEBUG: Discarding device description for \"%s\"...\n",
- addrname);
- return;
- }
-
- if (strchr(packet.object_value.string, ':') &&
- strchr(packet.object_value.string, ';'))
- {
- /*
- * Description is the IEEE-1284 device ID...
- */
-
- if (!device->id)
- device->id = strdup(packet.object_value.string);
-
- backendGetMakeModel(packet.object_value.string, make_model,
- sizeof(make_model));
- device->info = strdup(make_model);
- }
- else
- {
- /*
- * Description is plain text...
- */
-
- fix_make_model(make_model, packet.object_value.string,
- sizeof(make_model));
-
- device->info = strdup(packet.object_value.string);
- }
-
- if (!device->make_and_model)
- device->make_and_model = strdup(make_model);
-
- /*
- * List the device now if we have all the info...
- */
-
- if (device->id && device->info && device->make_and_model && device->uri)
- list_device(device);
- }
- else if (packet.request_id == DeviceIdRequest &&
- packet.object_type == CUPS_ASN1_OCTET_STRING)
- {
- /*
- * Update an existing cache entry...
- */
-
- char make_model[256]; /* Make and model */
-
-
- if (!device)
- {
- debug_printf("DEBUG: Discarding device ID for \"%s\"...\n",
- addrname);
- return;
- }
-
- if (device->id)
- free(device->id);
-
- device->id = strdup(packet.object_value.string);
+ case DEVICE_TYPE :
+ /*
+ * Got the device type response...
+ */
+
+ if (device)
+ {
+ debug_printf("DEBUG: Discarding duplicate device type for \"%s\"...\n",
+ addrname);
+ return;
+ }
+
+ /*
+ * Add the device and request the device data...
+ */
+
+ add_cache(&(packet.address), addrname, NULL, NULL, NULL);
+
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_DESCRIPTION, DescriptionOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_ID, DeviceIdOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_URI, UriOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_LOCATION, LocationOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_PRODUCT, LexmarkProductOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_PRODUCT, LexmarkProductOID2);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_ID, LexmarkDeviceIdOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_ID, RicohDeviceIdOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_PRODUCT, XeroxProductOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_ID, HPDeviceIdOID);
+ break;
+
+ case DEVICE_DESCRIPTION :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING)
+ {
+ /*
+ * Update an existing cache entry...
+ */
+
+ char make_model[256]; /* Make and model */
+
+
+ if (strchr((char *)packet.object_value.string.bytes, ':') &&
+ strchr((char *)packet.object_value.string.bytes, ';'))
+ {
+ /*
+ * Description is the IEEE-1284 device ID...
+ */
- /*
- * Convert the ID to a make and model string...
- */
+ char *ptr; /* Pointer into device ID */
- backendGetMakeModel(packet.object_value.string, make_model,
- sizeof(make_model));
- if (device->make_and_model)
- free(device->make_and_model);
+ for (ptr = (char *)packet.object_value.string.bytes; *ptr; ptr ++)
+ if (*ptr == '\n')
+ *ptr = ';'; /* A lot of bad printers put a newline */
+ if (!device->id)
+ device->id = strdup((char *)packet.object_value.string.bytes);
- device->make_and_model = strdup(make_model);
+ backendGetMakeModel((char *)packet.object_value.string.bytes,
+ make_model, sizeof(make_model));
- /*
- * List the device now if we have all the info...
- */
+ if (device->info)
+ free(device->info);
- if (device->id && device->info && device->make_and_model && device->uri)
- list_device(device);
- }
- else if (packet.request_id == DeviceUriRequest &&
- packet.object_type == CUPS_ASN1_OCTET_STRING)
- {
- /*
- * Update an existing cache entry...
- */
+ device->info = strdup(make_model);
+ }
+ else
+ {
+ /*
+ * Description is plain text...
+ */
- if (!device)
- {
- debug_printf("DEBUG: Discarding device URI for \"%s\"...\n",
- addrname);
- return;
- }
+ fix_make_model(make_model, (char *)packet.object_value.string.bytes,
+ sizeof(make_model));
- if (!strncmp(packet.object_value.string, "lpr:", 4))
- {
- /*
- * We want "lpd://..." for the URI...
- */
+ if (device->info)
+ free(device->info);
- packet.object_value.string[2] = 'd';
- }
+ device->info = strdup((char *)packet.object_value.string.bytes);
+ }
- device->uri = strdup(packet.object_value.string);
+ if (!device->make_and_model)
+ device->make_and_model = strdup(make_model);
+ }
+ break;
+
+ case DEVICE_ID :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
+ (!device->id ||
+ strlen(device->id) < packet.object_value.string.num_bytes))
+ {
+ /*
+ * Update an existing cache entry...
+ */
+
+ char make_model[256]; /* Make and model */
+ char *ptr; /* Pointer into device ID */
+
+ for (ptr = (char *)packet.object_value.string.bytes; *ptr; ptr ++)
+ if (*ptr == '\n')
+ *ptr = ';'; /* A lot of bad printers put a newline */
+ if (device->id)
+ free(device->id);
+
+ device->id = strdup((char *)packet.object_value.string.bytes);
+
+ /*
+ * Convert the ID to a make and model string...
+ */
+
+ backendGetMakeModel((char *)packet.object_value.string.bytes,
+ make_model, sizeof(make_model));
+ if (device->make_and_model)
+ free(device->make_and_model);
+
+ device->make_and_model = strdup(make_model);
+ }
+ break;
+
+ case DEVICE_LOCATION :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
+ !device->location)
+ device->location = strdup((char *)packet.object_value.string.bytes);
+ break;
+
+ case DEVICE_PRODUCT :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
+ !device->id)
+ {
+ /*
+ * Update an existing cache entry...
+ */
+
+ if (!device->info)
+ device->info = strdup((char *)packet.object_value.string.bytes);
+
+ if (device->make_and_model)
+ free(device->make_and_model);
+
+ device->make_and_model = strdup((char *)packet.object_value.string.bytes);
+ }
+ break;
+
+ case DEVICE_URI :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
+ !device->uri && packet.object_value.string.num_bytes > 3)
+ {
+ /*
+ * Update an existing cache entry...
+ */
+
+ char scheme[32], /* URI scheme */
+ userpass[256], /* Username:password in URI */
+ hostname[256], /* Hostname in URI */
+ resource[1024]; /* Resource path in URI */
+ int port; /* Port number in URI */
+
+ if (!strncmp((char *)packet.object_value.string.bytes, "lpr:", 4))
+ {
+ /*
+ * We want "lpd://..." for the URI...
+ */
- /*
- * List the device now if we have all the info...
- */
+ packet.object_value.string.bytes[2] = 'd';
+ }
- if (device->id && device->info && device->make_and_model && device->uri)
- list_device(device);
+ if (httpSeparateURI(HTTP_URI_CODING_ALL,
+ (char *)packet.object_value.string.bytes,
+ scheme, sizeof(scheme),
+ userpass, sizeof(userpass),
+ hostname, sizeof(hostname), &port,
+ resource, sizeof(resource)) >= HTTP_URI_OK)
+ device->uri = strdup((char *)packet.object_value.string.bytes);
+ }
+ break;
}
}
*/
static void
-scan_devices(int fd) /* I - SNMP socket */
+scan_devices(int ipv4, /* I - SNMP IPv4 socket */
+ int ipv6) /* I - SNMP IPv6 socket */
{
+ int fd, /* File descriptor for this address */
+ busy; /* Are we busy processing something? */
char *address, /* Current address */
*community; /* Current community */
fd_set input; /* Input set for select() */
http_addrlist_t *addrs, /* List of addresses */
*addr; /* Current address */
snmp_cache_t *device; /* Current device */
+ char temp[1024]; /* Temporary address string */
- /*
- * Setup the request IDs...
- */
-
gettimeofday(&StartTime, NULL);
- DeviceTypeRequest = StartTime.tv_sec;
- DeviceDescRequest = StartTime.tv_sec + 1;
-
/*
* First send all of the broadcast queries...
*/
{
char ifname[255]; /* Interface name */
-
strlcpy(ifname, address + 4, sizeof(ifname));
if (ifname[0])
ifname[strlen(ifname) - 1] = '\0';
addrs = get_interface_addresses(ifname);
}
else
- addrs = httpAddrGetList(address, AF_INET, NULL);
+ addrs = httpAddrGetList(address, AF_UNSPEC, NULL);
if (!addrs)
{
community, address);
for (addr = addrs; addr; addr = addr->next)
+ {
+#ifdef AF_INET6
+ if (httpAddrFamily(&(addr->addr)) == AF_INET6)
+ fd = ipv6;
+ else
+#endif /* AF_INET6 */
+ fd = ipv4;
+
+ debug_printf("DEBUG: Sending get request to %s...\n",
+ httpAddrString(&(addr->addr), temp, sizeof(temp)));
+
_cupsSNMPWrite(fd, &(addr->addr), CUPS_SNMP_VERSION_1, community,
- CUPS_ASN1_GET_REQUEST, DeviceTypeRequest, DeviceTypeOID);
+ CUPS_ASN1_GET_REQUEST, DEVICE_TYPE, DeviceTypeOID);
+ }
}
httpAddrFreeList(addrs);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
- FD_SET(fd, &input);
+ FD_SET(ipv4, &input);
+ if (ipv6 >= 0)
+ FD_SET(ipv6, &input);
+
+ fd = ipv4 > ipv6 ? ipv4 : ipv6;
if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
{
- fprintf(stderr, "ERROR: %.3f select() for %d failed: %s\n", run_time(),
- fd, strerror(errno));
+ fprintf(stderr, "ERROR: %.3f select() for %d/%d failed: %s\n", run_time(),
+ ipv4, ipv6, strerror(errno));
break;
}
- if (FD_ISSET(fd, &input))
- read_snmp_response(fd);
- else
- break;
- }
+ busy = 0;
- /*
- * Finally, probe all of the printers we discovered to see how they are
- * connected...
- */
+ if (FD_ISSET(ipv4, &input))
+ {
+ read_snmp_response(ipv4);
+ busy = 1;
+ }
- for (device = (snmp_cache_t *)cupsArrayFirst(Devices);
- device;
- device = (snmp_cache_t *)cupsArrayNext(Devices))
- if (MaxRunTime > 0 && run_time() >= MaxRunTime)
- break;
- else if (!device->uri)
- probe_device(device);
+ if (ipv6 >= 0 && FD_ISSET(ipv6, &input))
+ {
+ read_snmp_response(ipv6);
+ busy = 1;
+ }
+
+ if (!busy)
+ {
+ /*
+ * List devices with complete information...
+ */
+
+ int sent_something = 0;
+
+ for (device = (snmp_cache_t *)cupsArrayFirst(Devices);
+ device;
+ device = (snmp_cache_t *)cupsArrayNext(Devices))
+ if (!device->sent && device->info && device->make_and_model)
+ {
+ if (device->uri)
+ list_device(device);
+ else
+ probe_device(device);
+
+ device->sent = sent_something = 1;
+ }
+
+ if (!sent_something)
+ break;
+ }
+ }
debug_printf("DEBUG: %.3f Scan complete!\n", run_time());
}
debug_printf("DEBUG: %.3f Trying %s://%s:%d...\n", run_time(),
port == 515 ? "lpd" : "socket", addrname, port);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ if ((fd = socket(httpAddrFamily(addr), SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "ERROR: Unable to create socket: %s\n",
strerror(errno));
return (-1);
}
- addr->ipv4.sin_port = htons(port);
+ _httpAddrSetPort(addr, port);
alarm(1);
- status = connect(fd, (void *)addr, httpAddrLength(addr));
+ status = connect(fd, (void *)addr, (socklen_t)httpAddrLength(addr));
close(fd);
alarm(0);
list_device(device);
}
-
-
-/*
- * End of "$Id: snmp.c 6649 2007-07-11 21:46:42Z mike $".
- */