2 * Common backend network APIs for CUPS.
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 2006-2007 by Easy Software Products, all rights reserved.
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 * "LICENSE" which should have been included with this file. If this
11 * file is missing or damaged, see the license at "http://www.cups.org/".
13 * This file is subject to the Apple OS-Developed Software exception.
17 * Include necessary headers.
20 #include "backend-private.h"
22 #include <sys/select.h>
26 * 'backendCheckSideChannel()' - Check the side-channel for pending requests.
31 backendCheckSideChannel(
32 int snmp_fd
, /* I - SNMP socket */
33 http_addr_t
*addr
) /* I - Address of device */
35 fd_set input
; /* Select input set */
36 struct timeval timeout
; /* Select timeout */
40 FD_SET(CUPS_SC_FD
, &input
);
42 timeout
.tv_sec
= timeout
.tv_usec
= 0;
44 if (select(CUPS_SC_FD
+ 1, &input
, NULL
, NULL
, &timeout
) > 0)
45 backendNetworkSideCB(-1, -1, snmp_fd
, addr
, 0);
50 * 'backendNetworkSideCB()' - Handle common network side-channel commands.
53 int /* O - -1 on error, 0 on success */
55 int print_fd
, /* I - Print file or -1 */
56 int device_fd
, /* I - Device file or -1 */
57 int snmp_fd
, /* I - SNMP socket */
58 http_addr_t
*addr
, /* I - Address of device */
59 int use_bc
) /* I - Use back-channel data? */
61 cups_sc_command_t command
; /* Request command */
62 cups_sc_status_t status
; /* Request/response status */
63 char data
[65536]; /* Request/response data */
64 int datalen
; /* Request/response data size */
65 const char *device_id
; /* 1284DEVICEID env var */
68 datalen
= sizeof(data
);
70 if (cupsSideChannelRead(&command
, &status
, data
, &datalen
, 1.0))
75 case CUPS_SC_CMD_DRAIN_OUTPUT
:
77 * Our sockets disable the Nagle algorithm and data is sent immediately.
81 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
82 else if (backendDrainOutput(print_fd
, device_fd
))
83 status
= CUPS_SC_STATUS_IO_ERROR
;
85 status
= CUPS_SC_STATUS_OK
;
90 case CUPS_SC_CMD_GET_BIDI
:
91 status
= CUPS_SC_STATUS_OK
;
92 data
[0] = (char)use_bc
;
96 case CUPS_SC_CMD_SNMP_GET
:
97 case CUPS_SC_CMD_SNMP_GET_NEXT
:
98 fprintf(stderr
, "DEBUG: CUPS_SC_CMD_SNMP_%s: %d (%s)\n",
99 command
== CUPS_SC_CMD_SNMP_GET
? "GET" : "GET_NEXT", datalen
,
104 status
= CUPS_SC_STATUS_BAD_MESSAGE
;
111 char *dataptr
; /* Pointer into data */
112 cups_snmp_t packet
; /* Packet from printer */
113 const char *snmp_value
; /* CUPS_SNMP_VALUE env var */
115 if ((snmp_value
= getenv("CUPS_SNMP_VALUE")) != NULL
)
117 const char *snmp_count
; /* CUPS_SNMP_COUNT env var */
118 int count
; /* Repetition count */
120 if ((snmp_count
= getenv("CUPS_SNMP_COUNT")) != NULL
)
122 if ((count
= atoi(snmp_count
)) <= 0)
128 for (dataptr
= data
+ strlen(data
) + 1;
129 count
> 0 && dataptr
< (data
+ sizeof(data
) - 1);
130 count
--, dataptr
+= strlen(dataptr
))
131 strlcpy(dataptr
, snmp_value
, sizeof(data
) - (size_t)(dataptr
- data
));
133 fprintf(stderr
, "DEBUG: Returning %s %s\n", data
,
134 data
+ strlen(data
) + 1);
136 status
= CUPS_SC_STATUS_OK
;
137 datalen
= (int)(dataptr
- data
);
141 if (!_cupsSNMPStringToOID(data
, packet
.object_name
, CUPS_SNMP_MAX_OID
))
143 status
= CUPS_SC_STATUS_BAD_MESSAGE
;
148 status
= CUPS_SC_STATUS_IO_ERROR
;
151 if (_cupsSNMPWrite(snmp_fd
, addr
, CUPS_SNMP_VERSION_1
,
152 _cupsSNMPDefaultCommunity(),
153 command
== CUPS_SC_CMD_SNMP_GET
?
154 CUPS_ASN1_GET_REQUEST
:
155 CUPS_ASN1_GET_NEXT_REQUEST
, 1,
158 if (_cupsSNMPRead(snmp_fd
, &packet
, 1.0))
160 size_t i
; /* Looping var */
163 if (!_cupsSNMPOIDToString(packet
.object_name
, data
, sizeof(data
)))
165 fputs("DEBUG: Bad OID returned!\n", stderr
);
169 datalen
= (int)strlen(data
) + 1;
170 dataptr
= data
+ datalen
;
172 switch (packet
.object_type
)
174 case CUPS_ASN1_BOOLEAN
:
175 snprintf(dataptr
, sizeof(data
) - (size_t)(dataptr
- data
), "%d", packet
.object_value
.boolean
);
176 datalen
+= (int)strlen(dataptr
);
179 case CUPS_ASN1_INTEGER
:
180 snprintf(dataptr
, sizeof(data
) - (size_t)(dataptr
- data
), "%d",
181 packet
.object_value
.integer
);
182 datalen
+= (int)strlen(dataptr
);
185 case CUPS_ASN1_BIT_STRING
:
186 case CUPS_ASN1_OCTET_STRING
:
187 if (packet
.object_value
.string
.num_bytes
< (sizeof(data
) - (size_t)(dataptr
- data
)))
188 i
= packet
.object_value
.string
.num_bytes
;
190 i
= sizeof(data
) - (size_t)(dataptr
- data
);
192 memcpy(dataptr
, packet
.object_value
.string
.bytes
, i
);
198 _cupsSNMPOIDToString(packet
.object_value
.oid
, dataptr
,
199 sizeof(data
) - (size_t)(dataptr
- data
));
200 datalen
+= (int)strlen(dataptr
);
203 case CUPS_ASN1_HEX_STRING
:
205 i
< packet
.object_value
.string
.num_bytes
&&
206 dataptr
< (data
+ sizeof(data
) - 3);
208 sprintf(dataptr
, "%02X", packet
.object_value
.string
.bytes
[i
]);
209 datalen
+= (int)strlen(dataptr
);
212 case CUPS_ASN1_COUNTER
:
213 snprintf(dataptr
, sizeof(data
) - (size_t)(dataptr
- data
), "%u", packet
.object_value
.counter
);
214 datalen
+= (int)strlen(dataptr
);
217 case CUPS_ASN1_GAUGE
:
218 snprintf(dataptr
, sizeof(data
) - (size_t)(dataptr
- data
), "%u", packet
.object_value
.gauge
);
219 datalen
+= (int)strlen(dataptr
);
222 case CUPS_ASN1_TIMETICKS
:
223 snprintf(dataptr
, sizeof(data
) - (size_t)(dataptr
- data
), "%u", packet
.object_value
.timeticks
);
224 datalen
+= (int)strlen(dataptr
);
228 fprintf(stderr
, "DEBUG: Unknown OID value type %02X.\n", packet
.object_type
);
230 case CUPS_ASN1_NULL_VALUE
:
235 fprintf(stderr
, "DEBUG: Returning %s %s\n", data
, data
+ datalen
);
237 status
= CUPS_SC_STATUS_OK
;
240 fputs("DEBUG: SNMP read error...\n", stderr
);
243 fputs("DEBUG: SNMP write error...\n", stderr
);
247 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
251 case CUPS_SC_CMD_GET_CONNECTED
:
252 status
= CUPS_SC_STATUS_OK
;
253 data
[0] = device_fd
!= -1;
257 case CUPS_SC_CMD_GET_DEVICE_ID
:
260 cups_snmp_t packet
; /* Packet from printer */
261 static const int ppmPrinterIEEE1284DeviceId
[] =
262 { CUPS_OID_ppmPrinterIEEE1284DeviceId
,1,-1 };
265 status
= CUPS_SC_STATUS_IO_ERROR
;
268 if (_cupsSNMPWrite(snmp_fd
, addr
, CUPS_SNMP_VERSION_1
,
269 _cupsSNMPDefaultCommunity(),
270 CUPS_ASN1_GET_REQUEST
, 1,
271 ppmPrinterIEEE1284DeviceId
))
273 if (_cupsSNMPRead(snmp_fd
, &packet
, 1.0) &&
274 packet
.object_type
== CUPS_ASN1_OCTET_STRING
)
276 strlcpy(data
, (char *)packet
.object_value
.string
.bytes
,
278 datalen
= (int)strlen(data
);
279 status
= CUPS_SC_STATUS_OK
;
286 if ((device_id
= getenv("1284DEVICEID")) != NULL
)
288 strlcpy(data
, device_id
, sizeof(data
));
289 datalen
= (int)strlen(data
);
290 status
= CUPS_SC_STATUS_OK
;
295 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
300 return (cupsSideChannelWrite(command
, status
, data
, datalen
, 1.0));