* specified OID.
* _cupsSNMPIsOIDPrefixed() - Test whether a SNMP response uses the
* specified OID prefix.
+ * _cupsSNMPOIDToString() - Convert an OID to a string.
* _cupsSNMPOpen() - Open a SNMP socket.
* _cupsSNMPRead() - Read and parse a SNMP response.
* _cupsSNMPSetDebug() - Enable/disable debug logging to stderr.
+ * _cupsSNMPStringToOID() - Convert a numeric OID string to an OID array.
* _cupsSNMPWalk() - Enumerate a group of OIDs.
* _cupsSNMPWrite() - Send an SNMP query packet.
* asn1_debug() - Decode an ASN1-encoded message.
*/
#include "globals.h"
+#include "debug.h"
#include "snmp-private.h"
#include <errno.h>
#ifdef HAVE_POLL
/*
* '_cupsSNMPClose()' - Close a SNMP socket.
- *
- * @since CUPS 1.4@
*/
void
_cupsSNMPClose(int fd) /* I - SNMP socket file descriptor */
{
+ DEBUG_printf(("_cupsSNMPClose(fd=%d)\n", fd));
+
#ifdef WIN32
closesocket(fd);
#else
* '_cupsSNMPCopyOID()' - Copy an OID.
*
* The array pointed to by "src" is terminated by the value -1.
- *
- * @since CUPS 1.4@
*/
int * /* O - New OID */
int i; /* Looping var */
+ DEBUG_printf(("_cupsSNMPCopyOID(dst=%p, src=%p, dstsize=%d)\n", dst, src,
+ dstsize));
+
for (i = 0, dstsize --; src[i] >= 0 && i < dstsize; i ++)
dst[i] = src[i];
*
* The default community name is the first community name found in the
* snmp.conf file. If no community name is defined there, "public" is used.
- *
- * @since CUPS 1.4@
*/
const char * /* O - Default community name */
_cups_globals_t *cg = _cupsGlobals(); /* Global data */
+ DEBUG_puts("_cupsSNMPDefaultCommunity()");
+
if (!cg->snmp_community[0])
{
strlcpy(cg->snmp_community, "public", sizeof(cg->snmp_community));
}
}
+ DEBUG_printf(("_cupsSNMPDefaultCommunity: Returning \"%s\"\n",
+ cg->snmp_community));
+
return (cg->snmp_community);
}
* '_cupsSNMPIsOID()' - Test whether a SNMP response contains the specified OID.
*
* The array pointed to by "oid" is terminated by the value -1.
- *
- * @since CUPS 1.4@
*/
int /* O - 1 if equal, 0 if not equal */
* Range check input...
*/
+ DEBUG_printf(("_cupsSNMPIsOID(packet=%p, oid=%p)\n", packet, oid));
+
if (!packet || !oid)
+ {
+ DEBUG_puts("_cupsSNMPIsOID: Returning 0");
+
return (0);
+ }
/*
* Compare OIDs...
i < CUPS_SNMP_MAX_OID && oid[i] >= 0 && packet->object_name[i] >= 0;
i ++)
if (oid[i] != packet->object_name[i])
+ {
+ DEBUG_puts("_cupsSNMPIsOID: Returning 0");
+
return (0);
+ }
+
+ DEBUG_printf(("_cupsSNMPIsOID: Returning %d\n",
+ i < CUPS_SNMP_MAX_OID && oid[i] == packet->object_name[i]));
return (i < CUPS_SNMP_MAX_OID && oid[i] == packet->object_name[i]);
}
* OID prefix.
*
* The array pointed to by "prefix" is terminated by the value -1.
- *
- * @since CUPS 1.4@
*/
int /* O - 1 if prefixed, 0 if not prefixed */
* Range check input...
*/
+ DEBUG_printf(("_cupsSNMPIsOIDPrefixed(packet=%p, prefix=%p)\n", packet,
+ prefix));
+
if (!packet || !prefix)
+ {
+ DEBUG_puts("_cupsSNMPIsOIDPrefixed: Returning 0");
+
return (0);
+ }
/*
* Compare OIDs...
i < CUPS_SNMP_MAX_OID && prefix[i] >= 0 && packet->object_name[i] >= 0;
i ++)
if (prefix[i] != packet->object_name[i])
+ {
+ DEBUG_puts("_cupsSNMPIsOIDPrefixed: Returning 0");
+
return (0);
+ }
+
+ DEBUG_printf(("_cupsSNMPIsOIDPrefixed: Returning %d\n",
+ i < CUPS_SNMP_MAX_OID));
return (i < CUPS_SNMP_MAX_OID);
}
+/*
+ * '_cupsSNMPOIDToString()' - Convert an OID to a string.
+ */
+
+
+char * /* O - New string or @code NULL@ on error */
+_cupsSNMPOIDToString(const int *src, /* I - OID */
+ char *dst, /* I - String buffer */
+ size_t dstsize) /* I - Size of string buffer */
+{
+ char *dstptr, /* Pointer into string buffer */
+ *dstend; /* End of string buffer */
+
+
+ DEBUG_printf(("_cupsSNMPOIDToString(src=%p, dst=%p, dstsize=" CUPS_LLFMT ")\n",
+ src, dst, CUPS_LLCAST dstsize));
+
+ /*
+ * Range check input...
+ */
+
+ if (!src || !dst || dstsize < 4)
+ return (NULL);
+
+ /*
+ * Loop through the OID array and build a string...
+ */
+
+ for (dstptr = dst, dstend = dstptr + dstsize - 1;
+ *src >= 0 && dstptr < dstend;
+ src ++, dstptr += strlen(dstptr))
+ snprintf(dstptr, dstend - dstptr + 1, ".%d", *src);
+
+ if (*src >= 0)
+ return (NULL);
+ else
+ return (dst);
+}
+
+
/*
* '_cupsSNMPOpen()' - Open a SNMP socket.
- *
- * @since CUPS 1.4@
*/
int /* O - SNMP socket file descriptor */
* Create the SNMP socket...
*/
+ DEBUG_printf(("_cupsSNMPOpen(family=%d)\n", family));
+
if ((fd = socket(family, SOCK_DGRAM, 0)) < 0)
+ {
+ DEBUG_printf(("_cupsSNMPOpen: Returning -1 (%s)\n", strerror(errno)));
+
return (-1);
+ }
/*
* Set the "broadcast" flag...
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
{
+ DEBUG_printf(("_cupsSNMPOpen: Returning -1 (%s)\n", strerror(errno)));
+
close(fd);
return (-1);
}
+ DEBUG_printf(("_cupsSNMPOpen: Returning %d\n", fd));
+
return (fd);
}
*
* If "timeout" is negative, @code _cupsSNMPRead@ will wait for a response
* indefinitely.
- *
- * @since CUPS 1.4@
*/
cups_snmp_t * /* O - SNMP packet or @code NULL@ if none */
_cupsSNMPRead(int fd, /* I - SNMP socket file descriptor */
- cups_snmp_t *packet, /* I - SNMP packet buffer */
- double timeout) /* I - Timeout in seconds */
+ cups_snmp_t *packet, /* I - SNMP packet buffer */
+ double timeout) /* I - Timeout in seconds */
{
unsigned char buffer[CUPS_SNMP_MAX_PACKET];
/* Data packet */
* Range check input...
*/
+ DEBUG_printf(("_cupsSNMPRead(fd=%d, packet=%p, timeout=%.1f)\n", fd, packet,
+ timeout));
+
if (fd < 0 || !packet)
+ {
+ DEBUG_puts("_cupsSNMPRead: Returning NULL");
+
return (NULL);
+ }
/*
* Optionally wait for a response...
*/
if (ready <= 0)
+ {
+ DEBUG_puts("_cupsSNMPRead: Returning NULL (timeout)");
+
return (NULL);
+ }
}
/*
if ((bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (void *)&address,
&addrlen)) < 0)
+ {
+ DEBUG_printf(("_cupsSNMPRead: Returning NULL (%s)\n", strerror(errno)));
+
return (NULL);
+ }
/*
* Look for the response status code in the SNMP message header...
* Return decoded data packet...
*/
+ DEBUG_puts("_cupsSNMPRead: Returning packet");
+
return (packet);
}
/*
* '_cupsSNMPSetDebug()' - Enable/disable debug logging to stderr.
- *
- * @since CUPS 1.4@
*/
void
_cups_globals_t *cg = _cupsGlobals(); /* Global data */
+ DEBUG_printf(("_cupsSNMPSetDebug(level=%d)\n", level));
+
cg->snmp_debug = level;
}
+/*
+ * '_cupsSNMPStringToOID()' - Convert a numeric OID string to an OID array.
+ *
+ * This function converts a string of the form ".N.N.N.N.N" to the
+ * corresponding OID array terminated by -1.
+ *
+ * @code NULL@ is returned if the array is not large enough or the string is
+ * not a valid OID number.
+ */
+
+int * /* O - Pointer to OID array or @code NULL@ on error */
+_cupsSNMPStringToOID(const char *src, /* I - OID string */
+ int *dst, /* I - OID array */
+ int dstsize)/* I - Number of integers in OID array */
+{
+ int *dstptr, /* Pointer into OID array */
+ *dstend; /* End of OID array */
+
+
+ DEBUG_printf(("_cupsSNMPStringToOID(src=\"%s\", dst=%p, dstsize=%d)\n",
+ src, dst, dstsize));
+
+ /*
+ * Range check input...
+ */
+
+ if (!src || !dst || dstsize < 2)
+ return (NULL);
+
+ /*
+ * Skip leading "."...
+ */
+
+ if (*src == '.')
+ src ++;
+
+ /*
+ * Loop to the end of the string...
+ */
+
+ for (dstend = dst + dstsize - 1, dstptr = dst, *dstptr = 0;
+ *src && dstptr < dstend;
+ src ++)
+ {
+ if (*src == '.')
+ {
+ dstptr ++;
+ *dstptr = 0;
+ }
+ else if (isdigit(*src & 255))
+ *dstptr = *dstptr * 10 + *src - '0';
+ else
+ break;
+ }
+
+ if (*src)
+ return (NULL);
+
+ /*
+ * Terminate the end of the OID array and return...
+ */
+
+ dstptr[1] = -1;
+
+ return (dst);
+}
+
+
/*
* '_cupsSNMPWalk()' - Enumerate a group of OIDs.
*
*
* If "timeout" is negative, @code _cupsSNMPWalk@ will wait for a response
* indefinitely.
- *
- * @since CUPS 1.4@
*/
int /* O - Number of OIDs found or -1 on error */
* Range check input...
*/
+ DEBUG_printf(("_cupsSNMPWalk(fd=%d, address=%p, version=%d, "
+ "community=\"%s\", prefix=%p, timeout=%.1f, cb=%p, data=%p)\n",
+ fd, address, version, community ? community : "(null)",
+ prefix, timeout, cb, data));
+
if (fd < 0 || !address || version != CUPS_SNMP_VERSION_1 || !community ||
!prefix || !cb)
+ {
+ DEBUG_puts("_cupsSNMPWalk: Returning -1");
+
return (-1);
+ }
/*
* Copy the OID prefix and then loop until we have no more OIDs...
if (!_cupsSNMPWrite(fd, address, version, community,
CUPS_ASN1_GET_NEXT_REQUEST, request_id,
packet.object_name))
+ {
+ DEBUG_puts("_cupsSNMPWalk: Returning -1");
+
return (-1);
+ }
if (!_cupsSNMPRead(fd, &packet, timeout))
+ {
+ DEBUG_puts("_cupsSNMPWalk: Returning -1");
+
return (-1);
+ }
if (!_cupsSNMPIsOIDPrefixed(&packet, prefix))
+ {
+ DEBUG_printf(("_cupsSNMPWalk: Returning %d\n", count));
+
return (count);
+ }
if (packet.error || packet.error_status)
+ {
+ DEBUG_printf(("_cupsSNMPWalk: Returning %d\n", count > 0 ? count : -1));
+
return (count > 0 ? count : -1);
+ }
count ++;
* '_cupsSNMPWrite()' - Send an SNMP query packet.
*
* The array pointed to by "oid" is terminated by the value -1.
- *
- * @since CUPS 1.4@
*/
int /* O - 1 on success, 0 on error */
unsigned char buffer[CUPS_SNMP_MAX_PACKET];
/* SNMP message buffer */
int bytes; /* Size of message */
+ http_addr_t temp; /* Copy of address */
/*
* Range check input...
*/
+ DEBUG_printf(("_cupsSNMPWrite(fd=%d, address=%p, version=%d, "
+ "community=\"%s\", request_type=%d, request_id=%u, oid=%p)\n",
+ fd, address, version, community ? community : "(null)",
+ request_type, request_id, oid));
+
if (fd < 0 || !address || version != CUPS_SNMP_VERSION_1 || !community ||
(request_type != CUPS_ASN1_GET_REQUEST &&
request_type != CUPS_ASN1_GET_NEXT_REQUEST) || request_id < 1 || !oid)
+ {
+ DEBUG_puts("_cupsSNMPWrite: Returning 0 (bad arguments)");
+
return (0);
+ }
/*
* Create the SNMP message...
if (oid[i] >= 0)
{
+ DEBUG_puts("_cupsSNMPWrite: Returning 0 (OID too big)");
+
errno = E2BIG;
return (0);
}
if (bytes < 0)
{
+ DEBUG_puts("_cupsSNMPWrite: Returning 0 (request too big)");
+
errno = E2BIG;
return (0);
}
* Send the message...
*/
+ temp = *address;
+
#ifdef AF_INET6
- if (address->addr.sa_family == AF_INET6)
- address->ipv6.sin6_port = htons(CUPS_SNMP_PORT);
+ if (temp.addr.sa_family == AF_INET6)
+ temp.ipv6.sin6_port = htons(CUPS_SNMP_PORT);
else
#endif /* AF_INET6 */
- address->ipv4.sin_port = htons(CUPS_SNMP_PORT);
+ temp.ipv4.sin_port = htons(CUPS_SNMP_PORT);
- return (sendto(fd, buffer, bytes, 0, (void *)address,
- httpAddrLength(address)) == bytes);
+ return (sendto(fd, buffer, bytes, 0, (void *)&temp,
+ httpAddrLength(&temp)) == bytes);
}