Esempio n. 1
0
static void
read_snmp_response(int fd)		/* I - SNMP socket file descriptor */
{
  char		addrname[256];		/* Source address name */
  cups_snmp_t	packet;			/* Decoded packet */
  snmp_cache_t	key,			/* Search key */
		*device;		/* Matching device */


 /*
  * Read the response data...
  */

  if (!_cupsSNMPRead(fd, &packet, -1.0))
  {
    fprintf(stderr, "ERROR: Unable to read data from socket: %s\n",
            strerror(errno));
    return;
  }

  if (HostNameLookups)
    httpAddrLookup(&(packet.address), addrname, sizeof(addrname));
  else
    httpAddrString(&(packet.address), addrname, sizeof(addrname));

  debug_printf("DEBUG: %.3f Received data from %s...\n", run_time(), addrname);

 /*
  * Look for the response status code in the SNMP message header...
  */

  if (packet.error)
  {
    fprintf(stderr, "ERROR: Bad SNMP packet from %s: %s\n", addrname,
            packet.error);

    return;
  }

  debug_printf("DEBUG: community=\"%s\"\n", packet.community);
  debug_printf("DEBUG: request-id=%d\n", packet.request_id);
  debug_printf("DEBUG: error-status=%d\n", packet.error_status);

  if (packet.error_status && packet.request_id != DEVICE_TYPE)
    return;

 /*
  * Find a matching device in the cache...
  */

  key.addrname = addrname;
  device       = (snmp_cache_t *)cupsArrayFind(Devices, &key);

 /*
  * Process the message...
  */

  switch (packet.request_id)
  {
    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_PRODUCT, XeroxProductOID);
        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...
	    */

            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)
	      device->id = strdup((char *)packet.object_value.string.bytes);

	    backendGetMakeModel((char *)packet.object_value.string.bytes,
				make_model, sizeof(make_model));

            if (device->info)
	      free(device->info);

	    device->info = strdup(make_model);
	  }
	  else
	  {
	   /*
	    * Description is plain text...
	    */

	    fix_make_model(make_model, (char *)packet.object_value.string.bytes,
			   sizeof(make_model));

            if (device->info)
	      free(device->info);

	    device->info = strdup((char *)packet.object_value.string.bytes);
	  }

	  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...
	    */

	    packet.object_value.string.bytes[2] = 'd';
	  }

          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;
  }
}
Esempio n. 2
0
int					/* O - Number of OIDs found or -1 on error */
_cupsSNMPWalk(int            fd,	/* I - SNMP socket */
              http_addr_t    *address,	/* I - Address to query */
	      int            version,	/* I - SNMP version */
	      const char     *community,/* I - Community name */
              const int      *prefix,	/* I - OID prefix */
	      double         timeout,	/* I - Timeout for each response in seconds */
	      cups_snmp_cb_t cb,	/* I - Function to call for each response */
	      void           *data)	/* I - User data pointer that is passed to the callback function */
{
  int		count = 0;		/* Number of OIDs found */
  int		request_id = 0;		/* Current request ID */
  cups_snmp_t	packet;			/* Current response packet */
  int		lastoid[CUPS_SNMP_MAX_OID];
					/* Last OID we got */


 /*
  * Range check input...
  */

  DEBUG_printf(("4_cupsSNMPWalk(fd=%d, address=%p, version=%d, "
                "community=\"%s\", prefix=%p, timeout=%.1f, cb=%p, data=%p)",
		fd, address, version, community, prefix, timeout, cb, data));

  if (fd < 0 || !address || version != CUPS_SNMP_VERSION_1 || !community ||
      !prefix || !cb)
  {
    DEBUG_puts("5_cupsSNMPWalk: Returning -1");

    return (-1);
  }

 /*
  * Copy the OID prefix and then loop until we have no more OIDs...
  */

  _cupsSNMPCopyOID(packet.object_name, prefix, CUPS_SNMP_MAX_OID);
  lastoid[0] = -1;

  for (;;)
  {
    request_id ++;

    if (!_cupsSNMPWrite(fd, address, version, community,
                        CUPS_ASN1_GET_NEXT_REQUEST, request_id,
		        packet.object_name))
    {
      DEBUG_puts("5_cupsSNMPWalk: Returning -1");

      return (-1);
    }

    if (!_cupsSNMPRead(fd, &packet, timeout))
    {
      DEBUG_puts("5_cupsSNMPWalk: Returning -1");

      return (-1);
    }

    if (!_cupsSNMPIsOIDPrefixed(&packet, prefix) ||
        _cupsSNMPIsOID(&packet, lastoid))
    {
      DEBUG_printf(("5_cupsSNMPWalk: Returning %d", count));

      return (count);
    }

    if (packet.error || packet.error_status)
    {
      DEBUG_printf(("5_cupsSNMPWalk: Returning %d", count > 0 ? count : -1));

      return (count > 0 ? count : -1);
    }

    _cupsSNMPCopyOID(lastoid, packet.object_name, CUPS_SNMP_MAX_OID);

    count ++;

    (*cb)(&packet, data);
  }
}
Esempio n. 3
0
static void
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() */
  struct timeval	timeout;	/* Timeout for select() */
  time_t		endtime;	/* End time for scan */
  http_addrlist_t	*addrs,		/* List of addresses */
			*addr;		/* Current address */
  snmp_cache_t		*device;	/* Current device */
  char			temp[1024];	/* Temporary address string */


  gettimeofday(&StartTime, NULL);

 /*
  * First send all of the broadcast queries...
  */

  for (address = (char *)cupsArrayFirst(Addresses);
       address;
       address = (char *)cupsArrayNext(Addresses))
  {
    if (!strcmp(address, "@LOCAL"))
      addrs = get_interface_addresses(NULL);
    else if (!strncmp(address, "@IF(", 4))
    {
      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_UNSPEC, NULL);

    if (!addrs)
    {
      fprintf(stderr, "ERROR: Unable to scan \"%s\"!\n", address);
      continue;
    }

    for (community = (char *)cupsArrayFirst(Communities);
         community;
	 community = (char *)cupsArrayNext(Communities))
    {
      debug_printf("DEBUG: Scanning for devices in \"%s\" via \"%s\"...\n",
        	   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, DEVICE_TYPE, DeviceTypeOID);
      }
    }

    httpAddrFreeList(addrs);
  }

 /*
  * Then read any responses that come in over the next 3 seconds...
  */

  endtime = time(NULL) + MaxRunTime;

  FD_ZERO(&input);

  while (time(NULL) < endtime)
  {
    timeout.tv_sec  = 2;
    timeout.tv_usec = 0;

    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/%d failed: %s\n", run_time(),
              ipv4, ipv6, strerror(errno));
      break;
    }

    busy = 0;

    if (FD_ISSET(ipv4, &input))
    {
      read_snmp_response(ipv4);
      busy = 1;
    }

    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());
}
Esempio n. 4
0
int					/* O - -1 on error, 0 on success */
backendNetworkSideCB(
    int         print_fd,		/* I - Print file or -1 */
    int         device_fd,		/* I - Device file or -1 */
    int         snmp_fd,		/* I - SNMP socket */
    http_addr_t *addr,			/* I - Address of device */
    int         use_bc)			/* I - Use back-channel data? */
{
  cups_sc_command_t	command;	/* Request command */
  cups_sc_status_t	status;		/* Request/response status */
  char			data[65536];	/* Request/response data */
  int			datalen;	/* Request/response data size */
  const char		*device_id;	/* 1284DEVICEID env var */


  datalen = sizeof(data);

  if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
    return (-1);

  switch (command)
  {
    case CUPS_SC_CMD_DRAIN_OUTPUT :
       /*
        * Our sockets disable the Nagle algorithm and data is sent immediately.
	*/

        if (device_fd < 0)
	  status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
	else if (backendDrainOutput(print_fd, device_fd))
	  status = CUPS_SC_STATUS_IO_ERROR;
	else
          status = CUPS_SC_STATUS_OK;

	datalen = 0;
        break;

    case CUPS_SC_CMD_GET_BIDI :
	status  = CUPS_SC_STATUS_OK;
        data[0] = (char)use_bc;
        datalen = 1;
        break;

    case CUPS_SC_CMD_SNMP_GET :
    case CUPS_SC_CMD_SNMP_GET_NEXT :
        fprintf(stderr, "DEBUG: CUPS_SC_CMD_SNMP_%s: %d (%s)\n",
	        command == CUPS_SC_CMD_SNMP_GET ? "GET" : "GET_NEXT", datalen,
		data);

        if (datalen < 2)
	{
	  status  = CUPS_SC_STATUS_BAD_MESSAGE;
	  datalen = 0;
	  break;
	}

        if (snmp_fd >= 0)
	{
	  char		*dataptr;	/* Pointer into data */
	  cups_snmp_t	packet;		/* Packet from printer */
          const char	*snmp_value;	/* CUPS_SNMP_VALUE env var */

          if ((snmp_value = getenv("CUPS_SNMP_VALUE")) != NULL)
          {
            const char	*snmp_count;	/* CUPS_SNMP_COUNT env var */
            int		count;		/* Repetition count */

            if ((snmp_count = getenv("CUPS_SNMP_COUNT")) != NULL)
            {
              if ((count = atoi(snmp_count)) <= 0)
                count = 1;
            }
            else
              count = 1;

	    for (dataptr = data + strlen(data) + 1;
	         count > 0 && dataptr < (data + sizeof(data) - 1);
	         count --, dataptr += strlen(dataptr))
	      strlcpy(dataptr, snmp_value, sizeof(data) - (size_t)(dataptr - data));

	    fprintf(stderr, "DEBUG: Returning %s %s\n", data,
	            data + strlen(data) + 1);

	    status  = CUPS_SC_STATUS_OK;
	    datalen = (int)(dataptr - data);
	    break;
          }

          if (!_cupsSNMPStringToOID(data, packet.object_name, CUPS_SNMP_MAX_OID))
	  {
	    status  = CUPS_SC_STATUS_BAD_MESSAGE;
	    datalen = 0;
	    break;
	  }

          status  = CUPS_SC_STATUS_IO_ERROR;
	  datalen = 0;

          if (_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
	                     _cupsSNMPDefaultCommunity(),
	                     command == CUPS_SC_CMD_SNMP_GET ?
			         CUPS_ASN1_GET_REQUEST :
				 CUPS_ASN1_GET_NEXT_REQUEST, 1,
			     packet.object_name))
          {
	    if (_cupsSNMPRead(snmp_fd, &packet, 1.0))
	    {
	      size_t	i;		/* Looping var */


              if (!_cupsSNMPOIDToString(packet.object_name, data, sizeof(data)))
	      {
	        fputs("DEBUG: Bad OID returned!\n", stderr);
	        break;
	      }

	      datalen = (int)strlen(data) + 1;
              dataptr = data + datalen;

	      switch (packet.object_type)
	      {
	        case CUPS_ASN1_BOOLEAN :
		    snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%d", packet.object_value.boolean);
	            datalen += (int)strlen(dataptr);
		    break;

	        case CUPS_ASN1_INTEGER :
		    snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%d",
		             packet.object_value.integer);
	            datalen += (int)strlen(dataptr);
		    break;

	        case CUPS_ASN1_BIT_STRING :
	        case CUPS_ASN1_OCTET_STRING :
		    if (packet.object_value.string.num_bytes < (sizeof(data) - (size_t)(dataptr - data)))
		      i = packet.object_value.string.num_bytes;
		    else
		      i = sizeof(data) - (size_t)(dataptr - data);

		    memcpy(dataptr, packet.object_value.string.bytes, i);

                    datalen += (int)i;
		    break;

	        case CUPS_ASN1_OID :
		    _cupsSNMPOIDToString(packet.object_value.oid, dataptr,
		                         sizeof(data) - (size_t)(dataptr - data));
	            datalen += (int)strlen(dataptr);
		    break;

                case CUPS_ASN1_HEX_STRING :
		    for (i = 0;
		         i < packet.object_value.string.num_bytes &&
			     dataptr < (data + sizeof(data) - 3);
			 i ++, dataptr += 2)
		      sprintf(dataptr, "%02X", packet.object_value.string.bytes[i]);
	            datalen += (int)strlen(dataptr);
		    break;

                case CUPS_ASN1_COUNTER :
		    snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%u", packet.object_value.counter);
	            datalen += (int)strlen(dataptr);
		    break;

                case CUPS_ASN1_GAUGE :
		    snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%u", packet.object_value.gauge);
	            datalen += (int)strlen(dataptr);
		    break;

                case CUPS_ASN1_TIMETICKS :
		    snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%u", packet.object_value.timeticks);
	            datalen += (int)strlen(dataptr);
		    break;

                default :
	            fprintf(stderr, "DEBUG: Unknown OID value type %02X.\n", packet.object_type);

		case CUPS_ASN1_NULL_VALUE :
		    dataptr[0] = '\0';
		    break;
              }

	      fprintf(stderr, "DEBUG: Returning %s %s\n", data, data + datalen);

	      status = CUPS_SC_STATUS_OK;
	    }
	    else
	      fputs("DEBUG: SNMP read error...\n", stderr);
	  }
	  else
	    fputs("DEBUG: SNMP write error...\n", stderr);
	  break;
        }

        status  = CUPS_SC_STATUS_NOT_IMPLEMENTED;
	datalen = 0;
	break;

    case CUPS_SC_CMD_GET_CONNECTED :
	status  = CUPS_SC_STATUS_OK;
        data[0] = device_fd != -1;
        datalen = 1;
        break;

    case CUPS_SC_CMD_GET_DEVICE_ID :
        if (snmp_fd >= 0)
	{
	  cups_snmp_t	packet;		/* Packet from printer */
	  static const int ppmPrinterIEEE1284DeviceId[] =
	  		{ CUPS_OID_ppmPrinterIEEE1284DeviceId,1,-1 };


          status  = CUPS_SC_STATUS_IO_ERROR;
	  datalen = 0;

          if (_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
	                     _cupsSNMPDefaultCommunity(),
	                     CUPS_ASN1_GET_REQUEST, 1,
			     ppmPrinterIEEE1284DeviceId))
          {
	    if (_cupsSNMPRead(snmp_fd, &packet, 1.0) &&
	        packet.object_type == CUPS_ASN1_OCTET_STRING)
	    {
	      strlcpy(data, (char *)packet.object_value.string.bytes,
	              sizeof(data));
	      datalen = (int)strlen(data);
	      status  = CUPS_SC_STATUS_OK;
	    }
	  }

	  break;
        }

	if ((device_id = getenv("1284DEVICEID")) != NULL)
	{
	  strlcpy(data, device_id, sizeof(data));
	  datalen = (int)strlen(data);
	  status  = CUPS_SC_STATUS_OK;
	  break;
	}

    default :
        status  = CUPS_SC_STATUS_NOT_IMPLEMENTED;
	datalen = 0;
	break;
  }

  return (cupsSideChannelWrite(command, status, data, datalen, 1.0));
}
Esempio n. 5
0
static int				/* O - 1 on success, 0 on error */
show_oid(int         fd,		/* I - SNMP socket */
         const char  *community,	/* I - Community name */
	 http_addr_t *addr,		/* I - Address to query */
         const char  *s,		/* I - OID to query */
	 int         walk)		/* I - Walk OIDs? */
{
  int		i;			/* Looping var */
  int		oid[CUPS_SNMP_MAX_OID];	/* OID */
  cups_snmp_t	packet;			/* SNMP packet */
  char		temp[1024];		/* Temporary OID string */


  if (!_cupsSNMPStringToOID(s, oid, sizeof(oid) / sizeof(oid[0])))
  {
    puts("testsnmp: Bad OID");
    return (0);
  }

  if (walk)
  {
    printf("_cupsSNMPWalk(%s): ", _cupsSNMPOIDToString(oid, temp, sizeof(temp)));

    if (_cupsSNMPWalk(fd, addr, CUPS_SNMP_VERSION_1, community, oid, 5.0,
                     print_packet, NULL) < 0)
    {
      printf("FAIL (%s)\n", strerror(errno));
      return (0);
    }
  }
  else
  {
    printf("_cupsSNMPWrite(%s): ", _cupsSNMPOIDToString(oid, temp, sizeof(temp)));

    if (!_cupsSNMPWrite(fd, addr, CUPS_SNMP_VERSION_1, community,
		       CUPS_ASN1_GET_REQUEST, 1, oid))
    {
      printf("FAIL (%s)\n", strerror(errno));
      return (0);
    }

    puts("PASS");

    fputs("_cupsSNMPRead(5.0): ", stdout);

    if (!_cupsSNMPRead(fd, &packet, 5.0))
    {
      puts("FAIL (timeout)");
      return (0);
    }

    if (!_cupsSNMPIsOID(&packet, oid))
    {
      printf("FAIL (bad OID %d", packet.object_name[0]);
      for (i = 1; packet.object_name[i] >= 0; i ++)
	printf(".%d", packet.object_name[i]);
      puts(")");
      return (0);
    }

    if (packet.error)
    {
      printf("FAIL (%s)\n", packet.error);
      return (0);
    }

    puts("PASS");

    print_packet(&packet, NULL);
  }

  return (1);
}
Esempio n. 6
0
static void
backend_init_supplies(
    int         snmp_fd,		/* I - SNMP socket */
    http_addr_t *addr)			/* I - Printer address */
{
  int		i,			/* Looping var */
		type;			/* Current marker type */
  cups_file_t	*cachefile;		/* Cache file */
  const char	*cachedir;		/* CUPS_CACHEDIR value */
  char		addrstr[1024],		/* Address string */
		cachefilename[1024],	/* Cache filename */
		description[CUPS_SNMP_MAX_STRING],
					/* Device description string */
		value[CUPS_MAX_SUPPLIES * (CUPS_SNMP_MAX_STRING * 4 + 3)],
					/* Value string */
		*ptr,			/* Pointer into value string */
		*name_ptr;		/* Pointer into name string */
  cups_snmp_t	packet;			/* SNMP response packet */
  ppd_file_t	*ppd;			/* PPD file for this queue */
  ppd_attr_t	*ppdattr;		/* cupsSNMPSupplies attribute */
  static const char * const types[] =	/* Supply types */
		{
		  "other",
		  "unknown",
		  "toner",
		  "waste-toner",
		  "ink",
		  "ink-cartridge",
		  "ink-ribbon",
		  "waste-ink",
		  "opc",
		  "developer",
		  "fuser-oil",
		  "solid-wax",
		  "ribbon-wax",
		  "waste-wax",
		  "fuser",
		  "corona-wire",
		  "fuser-oil-wick",
		  "cleaner-unit",
		  "fuser-cleaning-pad",
		  "transfer-unit",
		  "toner-cartridge",
		  "fuser-oiler",
		  "water",
		  "waste-water",
		  "glue-water-additive",
		  "waste-paper",
		  "binding-supply",
		  "banding-supply",
		  "stitching-wire",
		  "shrink-wrap",
		  "paper-wrap",
		  "staples",
		  "inserts",
		  "covers"
		};


 /*
  * Reset state information...
  */

  current_addr  = *addr;
  current_state = -1;
  num_supplies  = -1;
  charset       = -1;

  memset(supplies, 0, sizeof(supplies));

 /*
  * See if we should be getting supply levels via SNMP...
  */

  if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL ||
      ((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
       ppdattr->value && _cups_strcasecmp(ppdattr->value, "true")))
  {
    ppdClose(ppd);
    return;
  }

  if ((ppdattr = ppdFindAttr(ppd, "cupsSNMPQuirks", NULL)) != NULL)
  {
    if (!_cups_strcasecmp(ppdattr->value, "capacity"))
      quirks |= CUPS_SNMP_CAPACITY;
  }

  ppdClose(ppd);

 /*
  * Get the device description...
  */

  if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
		     _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
		     hrDeviceDescr))
    return;

  if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
      packet.object_type != CUPS_ASN1_OCTET_STRING)
  {
    strlcpy(description, "Unknown", sizeof(description));
    num_supplies = 0;
  }
  else
    strlcpy(description, (char *)packet.object_value.string.bytes,
            sizeof(description));

  fprintf(stderr, "DEBUG2: hrDeviceDesc=\"%s\"\n", description);

 /*
  * See if we have already queried this device...
  */

  httpAddrString(addr, addrstr, sizeof(addrstr));

  if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
    cachedir = CUPS_CACHEDIR;

  snprintf(cachefilename, sizeof(cachefilename), "%s/%s.snmp", cachedir,
           addrstr);

  if ((cachefile = cupsFileOpen(cachefilename, "r")) != NULL)
  {
   /*
    * Yes, read the cache file:
    *
    *     3 num_supplies charset
    *     device description
    *     supply structures...
    */

    if (cupsFileGets(cachefile, value, sizeof(value)))
    {
      if (sscanf(value, "3 %d%d", &num_supplies, &charset) == 2 &&
          num_supplies <= CUPS_MAX_SUPPLIES &&
          cupsFileGets(cachefile, value, sizeof(value)))
      {
        if (!strcmp(description, value))
	  cupsFileRead(cachefile, (char *)supplies,
	               (size_t)num_supplies * sizeof(backend_supplies_t));
        else
	{
	  num_supplies = -1;
	  charset      = -1;
	}
      }
      else
      {
        num_supplies = -1;
	charset      = -1;
      }
    }

    cupsFileClose(cachefile);
  }

 /*
  * If the cache information isn't correct, scan for supplies...
  */

  if (charset < 0)
  {
   /*
    * Get the configured character set...
    */

    int	oid[CUPS_SNMP_MAX_OID];		/* OID for character set */


    if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
			_cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
			prtGeneralCurrentLocalization))
      return;

    if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
	packet.object_type != CUPS_ASN1_INTEGER)
    {
      fprintf(stderr,
              "DEBUG: prtGeneralCurrentLocalization type is %x, expected %x!\n",
	      packet.object_type, CUPS_ASN1_INTEGER);
      return;
    }

    fprintf(stderr, "DEBUG2: prtGeneralCurrentLocalization=%d\n",
            packet.object_value.integer);

    _cupsSNMPCopyOID(oid, prtLocalizationCharacterSet, CUPS_SNMP_MAX_OID);
    oid[prtLocalizationCharacterSetOffset - 2] = packet.object_value.integer;


    if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
			_cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
			oid))
      return;

    if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
	packet.object_type != CUPS_ASN1_INTEGER)
    {
      fprintf(stderr,
              "DEBUG: prtLocalizationCharacterSet type is %x, expected %x!\n",
	      packet.object_type, CUPS_ASN1_INTEGER);
      return;
    }

    fprintf(stderr, "DEBUG2: prtLocalizationCharacterSet=%d\n",
	    packet.object_value.integer);
    charset = packet.object_value.integer;
  }

  if (num_supplies < 0)
  {
   /*
    * Walk the printer configuration information...
    */

    _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
		  _cupsSNMPDefaultCommunity(), prtMarkerSuppliesEntry,
		  CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
  }

 /*
  * Save the cached information...
  */

  if (num_supplies < 0)
    num_supplies = 0;

  if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL)
  {
    cupsFilePrintf(cachefile, "3 %d %d\n", num_supplies, charset);
    cupsFilePrintf(cachefile, "%s\n", description);

    if (num_supplies > 0)
      cupsFileWrite(cachefile, (char *)supplies,
                    (size_t)num_supplies * sizeof(backend_supplies_t));

    cupsFileClose(cachefile);
  }

  if (num_supplies <= 0)
    return;

 /*
  * Get the colors...
  */

  for (i = 0; i < num_supplies; i ++)
    strlcpy(supplies[i].color, "none", sizeof(supplies[i].color));

  _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
                _cupsSNMPDefaultCommunity(), prtMarkerColorantValue,
	        CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);

 /*
  * Output the marker-colors attribute...
  */

  for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
  {
    if (i)
      *ptr++ = ',';

    strlcpy(ptr, supplies[i].color, sizeof(value) - (size_t)(ptr - value));
  }

  fprintf(stderr, "ATTR: marker-colors=%s\n", value);

 /*
  * Output the marker-names attribute (the double quoting is necessary to deal
  * with embedded quotes and commas in the marker names...)
  */

  for (i = 0, ptr = value; i < num_supplies; i ++)
  {
    if (i)
      *ptr++ = ',';

    *ptr++ = '\'';
    *ptr++ = '\"';
    for (name_ptr = supplies[i].name; *name_ptr;)
    {
      if (*name_ptr == '\\' || *name_ptr == '\"' || *name_ptr == '\'')
      {
        *ptr++ = '\\';
        *ptr++ = '\\';
        *ptr++ = '\\';
      }

      *ptr++ = *name_ptr++;
    }
    *ptr++ = '\"';
    *ptr++ = '\'';
  }

  *ptr = '\0';

  fprintf(stderr, "ATTR: marker-names=%s\n", value);

 /*
  * Output the marker-types attribute...
  */

  for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
  {
    if (i)
      *ptr++ = ',';

    type = supplies[i].type;

    if (type < CUPS_TC_other || type > CUPS_TC_covers)
      strlcpy(ptr, "unknown", sizeof(value) - (size_t)(ptr - value));
    else
      strlcpy(ptr, types[type - CUPS_TC_other], sizeof(value) - (size_t)(ptr - value));
  }

  fprintf(stderr, "ATTR: marker-types=%s\n", value);
}
Esempio n. 7
0
int					/* O - 0 on success, -1 on error */
backendSNMPSupplies(
    int         snmp_fd,		/* I - SNMP socket */
    http_addr_t *addr,			/* I - Printer address */
    int         *page_count,		/* O - Page count */
    int         *printer_state)		/* O - Printer state */
{
  if (!httpAddrEqual(addr, &current_addr))
    backend_init_supplies(snmp_fd, addr);
  else if (num_supplies > 0)
    _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
		  _cupsSNMPDefaultCommunity(), prtMarkerSuppliesLevel,
		  CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);

  if (page_count)
    *page_count = -1;

  if (printer_state)
    *printer_state = -1;

  if (num_supplies > 0)
  {
    int		i,			/* Looping var */
		percent,		/* Percent full */
		new_state,		/* New state value */
		change_state,		/* State change */
		new_supply_state = 0;	/* Supply state */
    char	value[CUPS_MAX_SUPPLIES * 4],
					/* marker-levels value string */
		*ptr;			/* Pointer into value string */
    cups_snmp_t	packet;			/* SNMP response packet */

   /*
    * Generate the marker-levels value string...
    */

    for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
    {
      if (supplies[i].max_capacity > 0 && supplies[i].level >= 0)
	percent = 100 * supplies[i].level / supplies[i].max_capacity;
      else if (supplies[i].level >= 0 && supplies[i].level <= 100 &&
               (quirks & CUPS_SNMP_CAPACITY))
        percent = supplies[i].level;
      else
        percent = 50;

      if (supplies[i].sclass == CUPS_TC_receptacleThatIsFilled)
        percent = 100 - percent;

      if (percent <= 5)
      {
        switch (supplies[i].type)
        {
          case CUPS_TC_toner :
          case CUPS_TC_tonerCartridge :
              if (percent <= 1)
                new_supply_state |= CUPS_TONER_EMPTY;
              else
                new_supply_state |= CUPS_TONER_LOW;
              break;
          case CUPS_TC_ink :
          case CUPS_TC_inkCartridge :
          case CUPS_TC_inkRibbon :
          case CUPS_TC_solidWax :
          case CUPS_TC_ribbonWax :
              if (percent <= 1)
                new_supply_state |= CUPS_MARKER_SUPPLY_EMPTY;
              else
                new_supply_state |= CUPS_MARKER_SUPPLY_LOW;
              break;
          case CUPS_TC_developer :
              if (percent <= 1)
                new_supply_state |= CUPS_DEVELOPER_EMPTY;
              else
                new_supply_state |= CUPS_DEVELOPER_LOW;
              break;
          case CUPS_TC_coronaWire :
          case CUPS_TC_fuser :
          case CUPS_TC_opc :
          case CUPS_TC_transferUnit :
              if (percent <= 1)
                new_supply_state |= CUPS_OPC_LIFE_OVER;
              else
                new_supply_state |= CUPS_OPC_NEAR_EOL;
              break;
#if 0 /* Because no two vendors report waste containers the same, disable SNMP reporting of same */
          case CUPS_TC_wasteInk :
          case CUPS_TC_wastePaper :
          case CUPS_TC_wasteToner :
          case CUPS_TC_wasteWater :
          case CUPS_TC_wasteWax :
              if (percent <= 1)
                new_supply_state |= CUPS_WASTE_FULL;
              else
                new_supply_state |= CUPS_WASTE_ALMOST_FULL;
              break;
#endif /* 0 */
          case CUPS_TC_cleanerUnit :
          case CUPS_TC_fuserCleaningPad :
              if (percent <= 1)
                new_supply_state |= CUPS_CLEANER_LIFE_OVER;
              else
                new_supply_state |= CUPS_CLEANER_NEAR_EOL;
              break;
        }
      }

      if (i)
        *ptr++ = ',';

      if ((supplies[i].max_capacity > 0 || (quirks & CUPS_SNMP_CAPACITY)) &&
          supplies[i].level >= 0)
        snprintf(ptr, sizeof(value) - (size_t)(ptr - value), "%d", percent);
      else
        strlcpy(ptr, "-1", sizeof(value) - (size_t)(ptr - value));
    }

    fprintf(stderr, "ATTR: marker-levels=%s\n", value);

    if (supply_state < 0)
      change_state = 0xffff;
    else
      change_state = supply_state ^ new_supply_state;

    fprintf(stderr, "DEBUG: new_supply_state=%x, change_state=%x\n",
            new_supply_state, change_state);

    for (i = 0;
         i < (int)(sizeof(supply_states) / sizeof(supply_states[0]));
         i ++)
      if (change_state & supply_states[i].bit)
      {
	fprintf(stderr, "STATE: %c%s\n",
		(new_supply_state & supply_states[i].bit) ? '+' : '-',
		supply_states[i].keyword);
      }

    supply_state = new_supply_state;

   /*
    * Get the current printer status bits...
    */

    if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
                       _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
                       hrPrinterDetectedErrorState))
      return (-1);

    if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
        packet.object_type != CUPS_ASN1_OCTET_STRING)
      return (-1);

    if (packet.object_value.string.num_bytes == 2)
      new_state = (packet.object_value.string.bytes[0] << 8) |
		  packet.object_value.string.bytes[1];
    else if (packet.object_value.string.num_bytes == 1)
      new_state = (packet.object_value.string.bytes[0] << 8);
    else
      new_state = 0;

    if (current_state < 0)
      change_state = 0xffff;
    else
      change_state = current_state ^ new_state;

    fprintf(stderr, "DEBUG: new_state=%x, change_state=%x\n", new_state,
            change_state);

    for (i = 0;
         i < (int)(sizeof(printer_states) / sizeof(printer_states[0]));
         i ++)
      if (change_state & printer_states[i].bit)
      {
	fprintf(stderr, "STATE: %c%s\n",
		(new_state & printer_states[i].bit) ? '+' : '-',
		printer_states[i].keyword);
      }

    current_state = new_state;

   /*
    * Get the current printer state...
    */

    if (printer_state)
    {
      if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
			 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
			 hrPrinterStatus))
	return (-1);

      if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
	  packet.object_type != CUPS_ASN1_INTEGER)
	return (-1);

      *printer_state = packet.object_value.integer;
    }

   /*
    * Get the current page count...
    */

    if (page_count)
    {
      if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
			 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
			 prtMarkerLifeCount))
	return (-1);

      if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
	  packet.object_type != CUPS_ASN1_COUNTER)
	return (-1);

      *page_count = packet.object_value.counter;
    }

    return (0);
  }
  else
    return (-1);
}