]> git.ipfire.org Git - thirdparty/cups.git/blob - backend/network.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / backend / network.c
1 /*
2 * Common backend network APIs for CUPS.
3 *
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 2006-2007 by Easy Software Products, all rights reserved.
6 *
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/".
12 *
13 * This file is subject to the Apple OS-Developed Software exception.
14 */
15
16 /*
17 * Include necessary headers.
18 */
19
20 #include "backend-private.h"
21 #include <limits.h>
22 #include <sys/select.h>
23
24
25 /*
26 * 'backendCheckSideChannel()' - Check the side-channel for pending requests.
27 */
28
29
30 void
31 backendCheckSideChannel(
32 int snmp_fd, /* I - SNMP socket */
33 http_addr_t *addr) /* I - Address of device */
34 {
35 fd_set input; /* Select input set */
36 struct timeval timeout; /* Select timeout */
37
38
39 FD_ZERO(&input);
40 FD_SET(CUPS_SC_FD, &input);
41
42 timeout.tv_sec = timeout.tv_usec = 0;
43
44 if (select(CUPS_SC_FD + 1, &input, NULL, NULL, &timeout) > 0)
45 backendNetworkSideCB(-1, -1, snmp_fd, addr, 0);
46 }
47
48
49 /*
50 * 'backendNetworkSideCB()' - Handle common network side-channel commands.
51 */
52
53 int /* O - -1 on error, 0 on success */
54 backendNetworkSideCB(
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? */
60 {
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 */
66
67
68 datalen = sizeof(data);
69
70 if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
71 return (-1);
72
73 switch (command)
74 {
75 case CUPS_SC_CMD_DRAIN_OUTPUT :
76 /*
77 * Our sockets disable the Nagle algorithm and data is sent immediately.
78 */
79
80 if (device_fd < 0)
81 status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
82 else if (backendDrainOutput(print_fd, device_fd))
83 status = CUPS_SC_STATUS_IO_ERROR;
84 else
85 status = CUPS_SC_STATUS_OK;
86
87 datalen = 0;
88 break;
89
90 case CUPS_SC_CMD_GET_BIDI :
91 status = CUPS_SC_STATUS_OK;
92 data[0] = (char)use_bc;
93 datalen = 1;
94 break;
95
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,
100 data);
101
102 if (datalen < 2)
103 {
104 status = CUPS_SC_STATUS_BAD_MESSAGE;
105 datalen = 0;
106 break;
107 }
108
109 if (snmp_fd >= 0)
110 {
111 char *dataptr; /* Pointer into data */
112 cups_snmp_t packet; /* Packet from printer */
113 const char *snmp_value; /* CUPS_SNMP_VALUE env var */
114
115 if ((snmp_value = getenv("CUPS_SNMP_VALUE")) != NULL)
116 {
117 const char *snmp_count; /* CUPS_SNMP_COUNT env var */
118 int count; /* Repetition count */
119
120 if ((snmp_count = getenv("CUPS_SNMP_COUNT")) != NULL)
121 {
122 if ((count = atoi(snmp_count)) <= 0)
123 count = 1;
124 }
125 else
126 count = 1;
127
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));
132
133 fprintf(stderr, "DEBUG: Returning %s %s\n", data,
134 data + strlen(data) + 1);
135
136 status = CUPS_SC_STATUS_OK;
137 datalen = (int)(dataptr - data);
138 break;
139 }
140
141 if (!_cupsSNMPStringToOID(data, packet.object_name, CUPS_SNMP_MAX_OID))
142 {
143 status = CUPS_SC_STATUS_BAD_MESSAGE;
144 datalen = 0;
145 break;
146 }
147
148 status = CUPS_SC_STATUS_IO_ERROR;
149 datalen = 0;
150
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,
156 packet.object_name))
157 {
158 if (_cupsSNMPRead(snmp_fd, &packet, 1.0))
159 {
160 size_t i; /* Looping var */
161
162
163 if (!_cupsSNMPOIDToString(packet.object_name, data, sizeof(data)))
164 {
165 fputs("DEBUG: Bad OID returned!\n", stderr);
166 break;
167 }
168
169 datalen = (int)strlen(data) + 1;
170 dataptr = data + datalen;
171
172 switch (packet.object_type)
173 {
174 case CUPS_ASN1_BOOLEAN :
175 snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%d", packet.object_value.boolean);
176 datalen += (int)strlen(dataptr);
177 break;
178
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);
183 break;
184
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;
189 else
190 i = sizeof(data) - (size_t)(dataptr - data);
191
192 memcpy(dataptr, packet.object_value.string.bytes, i);
193
194 datalen += (int)i;
195 break;
196
197 case CUPS_ASN1_OID :
198 _cupsSNMPOIDToString(packet.object_value.oid, dataptr,
199 sizeof(data) - (size_t)(dataptr - data));
200 datalen += (int)strlen(dataptr);
201 break;
202
203 case CUPS_ASN1_HEX_STRING :
204 for (i = 0;
205 i < packet.object_value.string.num_bytes &&
206 dataptr < (data + sizeof(data) - 3);
207 i ++, dataptr += 2)
208 sprintf(dataptr, "%02X", packet.object_value.string.bytes[i]);
209 datalen += (int)strlen(dataptr);
210 break;
211
212 case CUPS_ASN1_COUNTER :
213 snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%u", packet.object_value.counter);
214 datalen += (int)strlen(dataptr);
215 break;
216
217 case CUPS_ASN1_GAUGE :
218 snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%u", packet.object_value.gauge);
219 datalen += (int)strlen(dataptr);
220 break;
221
222 case CUPS_ASN1_TIMETICKS :
223 snprintf(dataptr, sizeof(data) - (size_t)(dataptr - data), "%u", packet.object_value.timeticks);
224 datalen += (int)strlen(dataptr);
225 break;
226
227 default :
228 fprintf(stderr, "DEBUG: Unknown OID value type %02X.\n", packet.object_type);
229
230 case CUPS_ASN1_NULL_VALUE :
231 dataptr[0] = '\0';
232 break;
233 }
234
235 fprintf(stderr, "DEBUG: Returning %s %s\n", data, data + datalen);
236
237 status = CUPS_SC_STATUS_OK;
238 }
239 else
240 fputs("DEBUG: SNMP read error...\n", stderr);
241 }
242 else
243 fputs("DEBUG: SNMP write error...\n", stderr);
244 break;
245 }
246
247 status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
248 datalen = 0;
249 break;
250
251 case CUPS_SC_CMD_GET_CONNECTED :
252 status = CUPS_SC_STATUS_OK;
253 data[0] = device_fd != -1;
254 datalen = 1;
255 break;
256
257 case CUPS_SC_CMD_GET_DEVICE_ID :
258 if (snmp_fd >= 0)
259 {
260 cups_snmp_t packet; /* Packet from printer */
261 static const int ppmPrinterIEEE1284DeviceId[] =
262 { CUPS_OID_ppmPrinterIEEE1284DeviceId,1,-1 };
263
264
265 status = CUPS_SC_STATUS_IO_ERROR;
266 datalen = 0;
267
268 if (_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
269 _cupsSNMPDefaultCommunity(),
270 CUPS_ASN1_GET_REQUEST, 1,
271 ppmPrinterIEEE1284DeviceId))
272 {
273 if (_cupsSNMPRead(snmp_fd, &packet, 1.0) &&
274 packet.object_type == CUPS_ASN1_OCTET_STRING)
275 {
276 strlcpy(data, (char *)packet.object_value.string.bytes,
277 sizeof(data));
278 datalen = (int)strlen(data);
279 status = CUPS_SC_STATUS_OK;
280 }
281 }
282
283 break;
284 }
285
286 if ((device_id = getenv("1284DEVICEID")) != NULL)
287 {
288 strlcpy(data, device_id, sizeof(data));
289 datalen = (int)strlen(data);
290 status = CUPS_SC_STATUS_OK;
291 break;
292 }
293
294 default :
295 status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
296 datalen = 0;
297 break;
298 }
299
300 return (cupsSideChannelWrite(command, status, data, datalen, 1.0));
301 }