cups_sc_status_t /* O - Status of command */ cupsSideChannelDoRequest( cups_sc_command_t command, /* I - Command to send */ char *data, /* O - Response data buffer pointer */ int *datalen, /* IO - Size of data buffer on entry, number of bytes in buffer on return */ double timeout) /* I - Timeout in seconds */ { cups_sc_status_t status; /* Status of command */ cups_sc_command_t rcommand; /* Response command */ if (cupsSideChannelWrite(command, CUPS_SC_STATUS_NONE, NULL, 0, timeout)) return (CUPS_SC_STATUS_TIMEOUT); if (cupsSideChannelRead(&rcommand, &status, data, datalen, timeout)) return (CUPS_SC_STATUS_TIMEOUT); if (rcommand != command) return (CUPS_SC_STATUS_BAD_MESSAGE); return (status); }
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)); }
cups_sc_status_t /* O - Status of first query of @code CUPS_SC_STATUS_OK@ on success */ cupsSideChannelSNMPWalk( const char *oid, /* I - First numeric OID to query */ double timeout, /* I - Timeout for each query in seconds */ cups_sc_walk_func_t cb, /* I - Function to call with each value */ void *context) /* I - Application-defined pointer to send to callback */ { cups_sc_status_t status; /* Status of command */ cups_sc_command_t rcommand; /* Response command */ char *real_data; /* Real data buffer for response */ int real_datalen, /* Real length of data buffer */ real_oidlen, /* Length of returned OID string */ oidlen; /* Length of first OID */ const char *current_oid; /* Current OID */ char last_oid[2048]; /* Last OID */ DEBUG_printf(("cupsSideChannelSNMPWalk(oid=\"%s\", timeout=%.3f, cb=%p, " "context=%p)", oid, timeout, cb, context)); /* * Range check input... */ if (!oid || !*oid || !cb) return (CUPS_SC_STATUS_BAD_MESSAGE); if ((real_data = _cupsBufferGet(_CUPS_SC_MAX_BUFFER)) == NULL) return (CUPS_SC_STATUS_TOO_BIG); /* * Loop until the OIDs don't match... */ current_oid = oid; oidlen = (int)strlen(oid); last_oid[0] = '\0'; do { /* * Send the request to the backend and wait for a response... */ if (cupsSideChannelWrite(CUPS_SC_CMD_SNMP_GET_NEXT, CUPS_SC_STATUS_NONE, current_oid, (int)strlen(current_oid) + 1, timeout)) { _cupsBufferRelease(real_data); return (CUPS_SC_STATUS_TIMEOUT); } real_datalen = _CUPS_SC_MAX_BUFFER; if (cupsSideChannelRead(&rcommand, &status, real_data, &real_datalen, timeout)) { _cupsBufferRelease(real_data); return (CUPS_SC_STATUS_TIMEOUT); } if (rcommand != CUPS_SC_CMD_SNMP_GET_NEXT) { _cupsBufferRelease(real_data); return (CUPS_SC_STATUS_BAD_MESSAGE); } if (status == CUPS_SC_STATUS_OK) { /* * Parse the response of the form "oid\0value"... */ if (strncmp(real_data, oid, oidlen) || real_data[oidlen] != '.' || !strcmp(real_data, last_oid)) { /* * Done with this set of OIDs... */ _cupsBufferRelease(real_data); return (CUPS_SC_STATUS_OK); } if (real_datalen < sizeof(real_data)) real_data[real_datalen] = '\0'; real_oidlen = strlen(real_data) + 1; real_datalen -= real_oidlen; /* * Call the callback with the OID and data... */ (*cb)(real_data, real_data + real_oidlen, real_datalen, context); /* * Update the current OID... */ current_oid = real_data; strlcpy(last_oid, current_oid, sizeof(last_oid)); } } while (status == CUPS_SC_STATUS_OK); _cupsBufferRelease(real_data); return (status); }
cups_sc_status_t /* O - Query status */ cupsSideChannelSNMPGet( const char *oid, /* I - OID to query */ char *data, /* I - Buffer for OID value */ int *datalen, /* IO - Size of OID buffer on entry, size of value on return */ double timeout) /* I - Timeout in seconds */ { cups_sc_status_t status; /* Status of command */ cups_sc_command_t rcommand; /* Response command */ char *real_data; /* Real data buffer for response */ int real_datalen, /* Real length of data buffer */ real_oidlen; /* Length of returned OID string */ DEBUG_printf(("cupsSideChannelSNMPGet(oid=\"%s\", data=%p, datalen=%p(%d), " "timeout=%.3f)", oid, data, datalen, datalen ? *datalen : -1, timeout)); /* * Range check input... */ if (!oid || !*oid || !data || !datalen || *datalen < 2) return (CUPS_SC_STATUS_BAD_MESSAGE); *data = '\0'; /* * Send the request to the backend and wait for a response... */ if (cupsSideChannelWrite(CUPS_SC_CMD_SNMP_GET, CUPS_SC_STATUS_NONE, oid, (int)strlen(oid) + 1, timeout)) return (CUPS_SC_STATUS_TIMEOUT); if ((real_data = _cupsBufferGet(_CUPS_SC_MAX_BUFFER)) == NULL) return (CUPS_SC_STATUS_TOO_BIG); real_datalen = _CUPS_SC_MAX_BUFFER; if (cupsSideChannelRead(&rcommand, &status, real_data, &real_datalen, timeout)) { _cupsBufferRelease(real_data); return (CUPS_SC_STATUS_TIMEOUT); } if (rcommand != CUPS_SC_CMD_SNMP_GET) { _cupsBufferRelease(real_data); return (CUPS_SC_STATUS_BAD_MESSAGE); } if (status == CUPS_SC_STATUS_OK) { /* * Parse the response of the form "oid\0value"... */ real_oidlen = strlen(real_data) + 1; real_datalen -= real_oidlen; if ((real_datalen + 1) > *datalen) { _cupsBufferRelease(real_data); return (CUPS_SC_STATUS_TOO_BIG); } memcpy(data, real_data + real_oidlen, real_datalen); data[real_datalen] = '\0'; *datalen = real_datalen; } _cupsBufferRelease(real_data); return (status); }