]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/snmp.c
Merge CUPS 1.4svn-r7524.
[thirdparty/cups.git] / backend / snmp.c
index 4e0cd1d6f764d40f400d8e0d1584e6f4f4d82409..0364ee2a2313b48ed0657348bedf44039f766f28 100644 (file)
@@ -48,7 +48,6 @@
 #include "backend-private.h"
 #include <cups/array.h>
 #include <cups/file.h>
-#include <cups/snmp.h>
 #include <cups/http-private.h>
 #include <regex.h>
 
 /*
  * This backend implements SNMP printer discovery.  It uses a broadcast-
  * based approach to get SNMP response packets from potential printers,
- * tries a mDNS lookup (Mac OS X only at present), a URI lookup based on
- * the device description string, and finally a probe of port 9100
- * (AppSocket) and 515 (LPD).
+ * requesting OIDs from the Host and Port Monitor MIBs, does a URI
+ * lookup based on the device description string, and finally a probe of
+ * port 9100 (AppSocket) and 515 (LPD).
  *
  * The current focus is on printers with internal network cards, although
- * the code also works with many external print servers as well.  Future
- * versions will support scanning for vendor-specific SNMP OIDs and the
- * new PWG Port Monitor MIB and not just the Host MIB OIDs.
+ * the code also works with many external print servers as well.
  *
  * The backend reads the snmp.conf file from the CUPS_SERVERROOT directory
  * which can contain comments, blank lines, or any number of the following
@@ -91,6 +88,7 @@
  * print servers:
  *
  *     Axis OfficeBasic, 5400, 5600
+ *     Brother
  *     EPSON
  *     Genicom
  *     HP JetDirect
@@ -125,6 +123,7 @@ typedef struct snmp_cache_s         /**** SNMP scan cache ****/
   char         *addrname,              /* Name of device */
                *uri,                   /* device-uri */
                *id,                    /* device-id */
+               *info,                  /* device-info */
                *make_and_model;        /* device-make-and-model */
 } snmp_cache_t;
 
@@ -133,7 +132,7 @@ typedef struct snmp_cache_s         /**** SNMP scan cache ****/
  * Private CUPS API to set the last error...
  */
 
-extern void    _cupsSetError(ipp_status_t status, const char *message);
+extern void            _cupsSetError(ipp_status_t status, const char *message);
 
 
 /*
@@ -175,10 +174,14 @@ static cups_array_t       *Addresses = NULL;
 static cups_array_t    *Communities = NULL;
 static cups_array_t    *Devices = NULL;
 static int             DebugLevel = 0;
-static int             DeviceDescOID[] = { CUPS_OID_hrDeviceDescr, 1, -1 };
+static const int       DeviceDescOID[] = { CUPS_OID_hrDeviceDescr, 1, -1 };
 static unsigned                DeviceDescRequest;
-static int             DeviceTypeOID[] = { CUPS_OID_hrDeviceType, 1, -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 cups_array_t    *DeviceURIs = NULL;
 static int             HostNameLookups = 0;
 static int             MaxRunTime = 120;
@@ -236,7 +239,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
   * Open the SNMP socket...
   */
 
-  if ((fd = cupsSNMPOpen(AF_INET)) < 0)
+  if ((fd = _cupsSNMPOpen(AF_INET)) < 0)
     return (1);
 
  /*
@@ -245,7 +248,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
 
   read_snmp_conf(argv[1]);
 
-  cupsSNMPSetDebug(DebugLevel);
+  _cupsSNMPSetDebug(DebugLevel);
 
   Devices = cupsArrayNew((cups_array_func_t)compare_cache, NULL);
 
@@ -259,7 +262,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
   * Close, free, and return with no errors...
   */
 
-  cupsSNMPClose(fd);
+  _cupsSNMPClose(fd);
 
   free_array(Addresses);
   free_array(Communities);
@@ -661,8 +664,9 @@ list_device(snmp_cache_t *cache)    /* I - Cached device */
     printf("network %s \"%s\" \"%s %s\" \"%s\"\n",
            cache->uri,
           cache->make_and_model ? cache->make_and_model : "Unknown",
-          cache->make_and_model ? cache->make_and_model : "Unknown",
-          cache->addrname, cache->id ? cache->id : "");
+          cache->info ? cache->info : "Unknown",
+          cache->addrname,
+          cache->id ? cache->id : "");
     fflush(stdout);
   }
 }
@@ -905,7 +909,7 @@ read_snmp_response(int fd)          /* I - SNMP socket file descriptor */
   * Read the response data...
   */
 
-  if (!cupsSNMPRead(fd, &packet, -1.0))
+  if (!_cupsSNMPRead(fd, &packet, -1.0))
   {
     fprintf(stderr, "ERROR: Unable to read data from socket: %s\n",
             strerror(errno));
@@ -968,8 +972,12 @@ read_snmp_response(int fd)         /* I - SNMP socket file descriptor */
 
     add_cache(&(packet.address), addrname, NULL, NULL, NULL);
 
-    cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community,
+    _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)
@@ -988,19 +996,19 @@ read_snmp_response(int fd)                /* I - SNMP socket file descriptor */
       return;
     }
 
-   /*
-    * Convert the description to a make and model string...
-    */
-
     if (strchr(packet.object_value.string, ':') &&
-        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));
+                         sizeof(make_model));
+      device->info = strdup(make_model);
     }
     else
     {
@@ -1009,15 +1017,92 @@ read_snmp_response(int fd)              /* I - SNMP socket file descriptor */
       */
 
       fix_make_model(make_model, packet.object_value.string,
-                     sizeof(make_model));
+                    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);
+
+   /*
+    * Convert the ID to a make and model string...
+    */
+
+    backendGetMakeModel(packet.object_value.string, make_model,
+                       sizeof(make_model));
     if (device->make_and_model)
       free(device->make_and_model);
 
     device->make_and_model = strdup(make_model);
 
-    probe_device(device);
+   /*
+    * 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 == DeviceUriRequest &&
+           packet.object_type == CUPS_ASN1_OCTET_STRING)
+  {
+   /*
+    * Update an existing cache entry...
+    */
+
+    if (!device)
+    {
+      debug_printf("DEBUG: Discarding device URI for \"%s\"...\n",
+                  addrname);
+      return;
+    }
+
+    if (!strncmp(packet.object_value.string, "lpr:", 4))
+    {
+     /*
+      * We want "lpd://..." for the URI...
+      */
+
+      packet.object_value.string[2] = 'd';
+    }
+
+    device->uri = strdup(packet.object_value.string);
+
+   /*
+    * List the device now if we have all the info...
+    */
+
+    if (device->id && device->info && device->make_and_model && device->uri)
+      list_device(device);
   }
 }
 
@@ -1103,7 +1188,7 @@ scan_devices(int fd)                      /* I - SNMP socket */
                   community, address);
 
       for (addr = addrs; addr; addr = addr->next)
-        cupsSNMPWrite(fd, &(addr->addr), CUPS_SNMP_VERSION_1, community,
+        _cupsSNMPWrite(fd, &(addr->addr), CUPS_SNMP_VERSION_1, community,
                      CUPS_ASN1_GET_REQUEST, DeviceTypeRequest, DeviceTypeOID);
     }