Print this page
Bump Apache dependency to Apache 2
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/print/mod_ipp/mod_ipp.c
+++ new/usr/src/lib/print/mod_ipp/mod_ipp.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 + * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
23 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 25 * Use is subject to license terms.
25 26 *
26 27 */
27 28
28 29 /* $Id: mod_ipp.c 149 2006-04-25 16:55:01Z njacobs $ */
29 30
30 -#pragma ident "%Z%%M% %I% %E% SMI"
31 -
32 31 /*
33 32 * Internet Printing Protocol (IPP) module for Apache.
34 33 */
35 34
36 35 #include "ap_config.h"
37 36
38 37 #include <stdio.h>
39 38 #include <time.h>
40 39 #include <sys/time.h>
41 40 #include <values.h>
42 41 #include <libintl.h>
43 42 #include <alloca.h>
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
44 43
45 44 #include "httpd.h"
46 45 #include "http_config.h"
47 46 #include "http_core.h"
48 47 #include "http_protocol.h"
49 48 #include "http_log.h"
50 49 #include "http_main.h"
51 50 #include "papi.h"
52 51 #ifndef APACHE_RELEASE /* appears to only exist in Apache 1.X */
53 52 #define APACHE2
54 -#include "apr_compat.h"
53 +#define ap_table_get apr_table_get
55 54 #endif
56 55
57 56 #include <papi.h>
58 57 #include <ipp-listener.h>
59 58
60 59 #ifndef APACHE2
61 60 module MODULE_VAR_EXPORT ipp_module;
62 61 #else
63 62 module AP_MODULE_DECLARE_DATA ipp_module;
64 63 #endif
65 64
66 65 #ifndef AP_INIT_TAKE1 /* Apache 2.X has this, but 1.3.X does not */
67 66 #define AP_INIT_NO_ARGS(directive, action, arg, where, mesg) \
68 67 { directive, action, arg, where, NO_ARGS, mesg }
69 68 #define AP_INIT_TAKE1(directive, action, arg, where, mesg) \
70 69 { directive, action, arg, where, TAKE1, mesg }
71 70 #define AP_INIT_TAKE2(directive, action, arg, where, mesg) \
72 71 { directive, action, arg, where, TAKE2, mesg }
73 72 #endif
74 73
75 74 typedef struct {
76 75 int conformance;
77 76 char *default_user;
78 77 char *default_svc;
79 78 papi_attribute_t **operations;
80 79 } IPPListenerConfig;
81 80
82 81 #ifdef DEBUG
83 82 void
84 83 dump_buffer(FILE *fp, char *tag, char *buffer, int bytes)
85 84 {
86 85 int i, j, ch;
87 86
88 87 fprintf(fp, "%s %d(0x%x) bytes\n", (tag ? tag : ""), bytes, bytes);
89 88 for (i = 0; i < bytes; i += 16) {
90 89 fprintf(fp, "%s ", (tag ? tag : ""));
91 90
92 91 for (j = 0; j < 16 && (i + j) < bytes; j ++)
93 92 fprintf(fp, " %02X", buffer[i + j] & 255);
94 93
95 94 while (j < 16) {
96 95 fprintf(fp, " ");
97 96 j++;
98 97 }
99 98
100 99 fprintf(fp, " ");
101 100 for (j = 0; j < 16 && (i + j) < bytes; j ++) {
102 101 ch = buffer[i + j] & 255;
103 102 if (ch < ' ' || ch == 127)
104 103 ch = '.';
105 104 putc(ch, fp);
106 105 }
107 106 putc('\n', fp);
108 107 }
109 108 fflush(fp);
110 109 }
111 110 #endif
112 111
113 112 static ssize_t
114 113 read_data(void *fd, void *buf, size_t siz)
115 114 {
116 115 ssize_t len_read;
117 116 request_rec *ap_r = (request_rec *)fd;
118 117
119 118 len_read = ap_get_client_block(ap_r, buf, siz);
120 119 #ifndef APACHE2
121 120 ap_reset_timeout(ap_r);
122 121 #endif
123 122
124 123 #ifdef DEBUG
125 124 fprintf(stderr, "read_data(0x%8.8x, 0x%8.8x, %d): %d",
126 125 fd, buf, siz, len_read);
127 126 if (len_read < 0)
128 127 fprintf(stderr, ": %s", strerror(errno));
129 128 putc('\n', stderr);
130 129 dump_buffer(stderr, "read_data:", buf, len_read);
131 130 #endif
132 131
133 132 return (len_read);
134 133 }
135 134
136 135 static ssize_t
137 136 write_data(void *fd, void *buf, size_t siz)
138 137 {
139 138 ssize_t len_written;
140 139 request_rec *ap_r = (request_rec *)fd;
141 140
142 141 #ifndef APACHE2
143 142 ap_reset_timeout(ap_r);
144 143 #endif
145 144 #ifdef DEBUG
146 145 dump_buffer(stderr, "write_data:", buf, siz);
147 146 #endif
148 147 len_written = ap_rwrite(buf, siz, ap_r);
149 148
150 149 return (len_written);
151 150 }
152 151
153 152 static void
154 153 discard_data(request_rec *r)
155 154 {
156 155 #ifdef APACHE2
157 156 (void) ap_discard_request_body(r);
158 157 #else
159 158 /*
160 159 * This is taken from ap_discard_request_body(). The reason we can't
161 160 * just use it in Apache 1.3 is that it does various timeout things we
162 161 * don't want it to do. Apache 2.0 doesn't do that, so we can safely
163 162 * use the normal function.
164 163 */
165 164 if (r->read_chunked || r->remaining > 0) {
166 165 char dumpbuf[HUGE_STRING_LEN];
167 166 int i;
168 167
169 168 do {
170 169 i = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN);
171 170 #ifdef DEBUG
172 171 dump_buffer(stderr, "discarded", dumpbuf, i);
173 172 #endif
174 173 } while (i > 0);
175 174 }
176 175 #endif
177 176 }
178 177
179 178 void _log_rerror(const char *file, int line, int level, request_rec *r,
180 179 const char *fmt, ...)
181 180 {
182 181 va_list args;
183 182 size_t size;
184 183 char *message = alloca(BUFSIZ);
185 184
186 185 va_start(args, fmt);
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
187 186 /*
188 187 * fill in the message. If the buffer is too small, allocate
189 188 * one that is large enough and fill it in.
190 189 */
191 190 if ((size = vsnprintf(message, BUFSIZ, fmt, args)) >= BUFSIZ)
192 191 if ((message = alloca(size)) != NULL)
193 192 vsnprintf(message, size, fmt, args);
194 193 va_end(args);
195 194
196 195 #ifdef APACHE2
197 - ap_log_rerror(file, line, level, NULL, r, message);
196 + ap_log_rerror(file, line, level, APR_SUCCESS, r, message);
198 197 #else
199 198 ap_log_rerror(file, line, level, r, message);
200 199 #endif
201 200 }
202 201
203 202 static int
204 203 ipp_handler(request_rec *r)
205 204 {
206 205 papi_attribute_t **request = NULL, **response = NULL;
207 206 IPPListenerConfig *config;
208 207 papi_status_t status;
209 208 int ret;
210 209
211 210 /* Really, IPP is all POST requests */
212 211 if (r->method_number != M_POST)
213 212 return (DECLINED);
214 213
215 214 #ifndef APACHE2
216 215 /*
217 216 * An IPP request must have a MIME type of "application/ipp"
218 217 * (RFC-2910, Section 4, page 19). If it doesn't match this
219 218 * MIME type, we should decline the request and let someone else
220 219 * try and handle it.
221 220 */
222 221 if (r->headers_in != NULL) {
223 222 char *mime_type = (char *)ap_table_get(r->headers_in,
224 223 "Content-Type");
225 224
226 225 if ((mime_type == NULL) ||
227 226 (strcasecmp(mime_type, "application/ipp") != 0))
228 227 return (DECLINED);
229 228 }
230 229 #endif
231 230 /* CHUNKED_DECHUNK might not work right for IPP? */
232 231 if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK)
233 232 return (ret);
234 233
235 234 if (!ap_should_client_block(r))
236 235 return (HTTP_INTERNAL_SERVER_ERROR);
237 236
238 237 #ifndef APACHE2
239 238 ap_soft_timeout("ipp_module: read/reply request ", r);
240 239 #endif
241 240 /* read the IPP request off the network */
242 241 status = ipp_read_message(read_data, r, &request, IPP_TYPE_REQUEST);
243 242
244 243 if (status != PAPI_OK)
245 244 _log_rerror(APLOG_MARK, APLOG_ERR, r,
246 245 "read failed: %s\n", papiStatusString(status));
247 246 #ifdef DEBUG
248 247 papiAttributeListPrint(stderr, request, "request (%d) ", getpid());
249 248 #endif
250 249
251 250 (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
252 251 "originating-host", (char *)
253 252 #ifdef APACHE2
254 253 ap_get_remote_host
255 254 (r->connection, r->per_dir_config, REMOTE_NAME, NULL));
256 255 #else
257 256 ap_get_remote_host
258 257 (r->connection, r->per_dir_config, REMOTE_NAME));
259 258 #endif
260 259
261 260 (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
262 261 "uri-port", ap_get_server_port(r));
263 262 if (r->headers_in != NULL) {
264 263 char *host = (char *)ap_table_get(r->headers_in, "Host");
265 264
266 265 if ((host == NULL) || (host[0] == '\0'))
267 266 host = (char *)ap_get_server_name(r);
268 267
269 268 (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
270 269 "uri-host", host);
271 270 }
272 271 (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
273 272 "uri-path", r->uri);
274 273
275 274 config = ap_get_module_config(r->per_dir_config, &ipp_module);
276 275 if (config != NULL) {
277 276 (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
278 277 "conformance", config->conformance);
279 278 (void) papiAttributeListAddCollection(&request, PAPI_ATTR_EXCL,
280 279 "operations", config->operations);
↓ open down ↓ |
73 lines elided |
↑ open up ↑ |
281 280 if (config->default_user != NULL)
282 281 (void) papiAttributeListAddString(&request,
283 282 PAPI_ATTR_EXCL, "default-user",
284 283 config->default_user);
285 284 if (config->default_svc != NULL)
286 285 (void) papiAttributeListAddString(&request,
287 286 PAPI_ATTR_EXCL, "default-service",
288 287 config->default_svc);
289 288 }
290 289
290 +#ifndef APACHE2
291 291 /*
292 292 * For Trusted Solaris, pass the fd number of the socket connection
293 293 * to the backend so the it can be forwarded to the backend print
294 294 * service to retrieve the sensativity label off of a multi-level
295 295 * port.
296 296 */
297 297 (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
298 298 "peer-socket", ap_bfileno(r->connection->client, B_RD));
299 +#endif
299 300
300 301 /* process the request */
301 302 status = ipp_process_request(request, &response, read_data, r);
302 303 if (status != PAPI_OK) {
303 304 errno = 0;
304 305 _log_rerror(APLOG_MARK, APLOG_ERR, r,
305 306 "request failed: %s\n", papiStatusString(status));
306 307 discard_data(r);
307 308 }
308 309 #ifdef DEBUG
309 310 fprintf(stderr, "processing result: %s\n", papiStatusString(status));
310 311 papiAttributeListPrint(stderr, response, "response (%d) ", getpid());
311 312 #endif
312 313
313 314 /*
314 315 * If the client is using chunking and we have not yet received the
315 316 * final "0" sized chunk, we need to discard any data that may
316 317 * remain in the post request.
317 318 */
318 319 if ((r->read_chunked != 0) &&
319 320 (ap_table_get(r->headers_in, "Content-Length") == NULL))
320 321 discard_data(r);
321 322
322 323 /* write an IPP response back to the network */
323 324 r->content_type = "application/ipp";
324 325
325 326 #ifndef APACHE2
326 327 ap_send_http_header(r);
327 328 #endif
328 329
329 330 status = ipp_write_message(write_data, r, response);
330 331 if (status != PAPI_OK)
331 332 _log_rerror(APLOG_MARK, APLOG_ERR, r,
332 333 "write failed: %s\n", papiStatusString(status));
333 334 #ifdef DEBUG
334 335 fprintf(stderr, "write result: %s\n", papiStatusString(status));
335 336 fflush(stderr);
336 337 #endif
337 338
338 339 papiAttributeListFree(request);
339 340 papiAttributeListFree(response);
340 341
341 342 #ifndef APACHE2
342 343 ap_kill_timeout(r);
343 344 if (ap_rflush(r) < 0)
344 345 _log_rerror(APLOG_MARK, APLOG_ERR, r,
345 346 "flush failed, response may not have been sent");
346 347 #endif
347 348
348 349 return (OK);
349 350 }
350 351
351 352
352 353 /*ARGSUSED1*/
353 354 static void *
354 355 create_ipp_dir_config(
355 356 #ifndef APACHE2
356 357 pool *p,
357 358 #else
358 359 apr_pool_t *p,
359 360 #endif
360 361 char *dirspec)
361 362 {
362 363 IPPListenerConfig *config =
363 364 #ifndef APACHE2
364 365 ap_pcalloc(p, sizeof (*config));
365 366 #else
366 367 apr_pcalloc(p, sizeof (*config));
367 368 #endif
368 369
369 370 if (config != NULL) {
370 371 (void) memset(config, 0, sizeof (*config));
371 372 config->conformance = IPP_PARSE_CONFORMANCE_RASH;
372 373 config->default_user = NULL;
373 374 config->default_svc = NULL;
374 375 (void) ipp_configure_operation(&config->operations, "required",
375 376 "enable");
376 377 }
377 378
378 379 return (config);
379 380 }
380 381
381 382 /*ARGSUSED0*/
382 383 static const char *
383 384 ipp_conformance(cmd_parms *cmd, void *cfg, const char *arg)
384 385 {
385 386 IPPListenerConfig *config = (IPPListenerConfig *)cfg;
386 387
387 388 if (strncasecmp(arg, "automatic", 4) == 0) {
388 389 config->conformance = IPP_PARSE_CONFORMANCE_RASH;
389 390 } else if (strcasecmp(arg, "1.0") == 0) {
390 391 config->conformance = IPP_PARSE_CONFORMANCE_LOOSE;
391 392 } else if (strcasecmp(arg, "1.1") == 0) {
↓ open down ↓ |
83 lines elided |
↑ open up ↑ |
392 393 config->conformance = IPP_PARSE_CONFORMANCE_STRICT;
393 394 } else {
394 395 return ("unknown conformance, try (automatic/1.0/1.1)");
395 396 }
396 397
397 398 return (NULL);
398 399 }
399 400
400 401 /*ARGSUSED0*/
401 402 static const char *
402 -ipp_operation(cmd_parms *cmd, void *cfg, char *op, char *toggle)
403 +ipp_operation(cmd_parms *cmd, void *cfg, const char *op, const char *toggle)
403 404 {
404 405 IPPListenerConfig *config = (IPPListenerConfig *)cfg;
405 406 papi_status_t status;
406 407
407 408 status = ipp_configure_operation(&config->operations, op, toggle);
408 409 switch (status) {
409 410 case PAPI_OK:
410 411 return (NULL);
411 412 case PAPI_BAD_ARGUMENT:
412 413 return (gettext("internal error (invalid argument)"));
413 414 default:
414 415 return (papiStatusString(status));
415 416 }
416 417
417 418 /* NOTREACHED */
418 419 /* return (gettext("contact your software vendor")); */
419 420 }
420 421
421 422 static const char *
422 423 ipp_default_user(cmd_parms *cmd, void *cfg, const char *arg)
423 424 {
424 425 IPPListenerConfig *config = (IPPListenerConfig *)cfg;
425 426
426 427 config->default_user = (char *)arg;
427 428
428 429 return (NULL);
429 430 }
430 431
431 432 static const char *
432 433 ipp_default_svc(cmd_parms *cmd, void *cfg, const char *arg)
433 434 {
434 435 IPPListenerConfig *config = (IPPListenerConfig *)cfg;
435 436
436 437 config->default_svc = (char *)arg;
437 438
438 439 return (NULL);
439 440 }
440 441
441 442 #ifdef DEBUG
442 443 /*ARGSUSED0*/
443 444 static const char *
444 445 ipp_module_hang(cmd_parms *cmd, void *cfg)
445 446 {
446 447 static int i = 1;
447 448
448 449 /* wait so we can attach a debugger, assign i = 0, and step through */
449 450 while (i);
450 451
451 452 return (NULL);
452 453 }
453 454 #endif /* DEBUG */
454 455
455 456 static const command_rec ipp_cmds[] =
456 457 {
457 458 AP_INIT_TAKE1("ipp-conformance", ipp_conformance, NULL, ACCESS_CONF,
458 459 "IPP protocol conformance (loose/strict)"),
459 460 AP_INIT_TAKE2("ipp-operation", ipp_operation, NULL, ACCESS_CONF,
460 461 "IPP protocol operations to enable/disable)"),
461 462 AP_INIT_TAKE1("ipp-default-user", ipp_default_user, NULL, ACCESS_CONF,
462 463 "default user for various operations"),
463 464 AP_INIT_TAKE1("ipp-default-service", ipp_default_svc, NULL, ACCESS_CONF,
464 465 "default service for various operations"),
465 466 #ifdef DEBUG
466 467 AP_INIT_NO_ARGS("ipp-module-hang", ipp_module_hang, NULL, ACCESS_CONF,
467 468 "hang the module until we can attach a debugger (no args)"),
468 469 #endif
469 470 { NULL }
470 471 };
471 472
472 473 #ifdef APACHE2
473 474 /*ARGSUSED0*/
474 475 static const char *
475 476 ipp_method(const request_rec *r)
476 477 {
477 478 return ("ipp");
478 479 }
479 480
480 481 /*ARGSUSED0*/
481 482 static unsigned short
482 483 ipp_port(const request_rec *r)
483 484 {
484 485 return (631);
485 486 }
486 487
487 488 /* Dispatch list for API hooks */
488 489 /*ARGSUSED0*/
489 490 static void
490 491 ipp_register_hooks(apr_pool_t *p)
491 492 {
492 493 static const char * const modules[] = { "mod_dir.c", NULL };
493 494
494 495 /* Need to make sure we don't get directory listings by accident */
495 496 ap_hook_handler(ipp_handler, NULL, modules, APR_HOOK_MIDDLE);
496 497 ap_hook_default_port(ipp_port, NULL, NULL, APR_HOOK_MIDDLE);
497 498 ap_hook_http_method(ipp_method, NULL, NULL, APR_HOOK_MIDDLE);
498 499 }
499 500
500 501 module AP_MODULE_DECLARE_DATA ipp_module = {
501 502 STANDARD20_MODULE_STUFF,
502 503 create_ipp_dir_config, /* create per-dir config */
503 504 NULL, /* merge per-dir config */
504 505 NULL, /* create per-server config */
505 506 NULL, /* merge per-server config */
506 507 ipp_cmds, /* table of config commands */
507 508 ipp_register_hooks /* register hooks */
508 509 };
509 510
510 511 #else /* Apache 1.X */
511 512
512 513 /* Dispatch list of content handlers */
513 514 static const handler_rec ipp_handlers[] = {
514 515 /*
515 516 * This handler association causes all IPP request with the
516 517 * correct MIME type to call the protocol handler.
517 518 */
518 519 { "application/ipp", ipp_handler },
519 520 /*
520 521 * This hander association is causes everything to go through the IPP
521 522 * protocol request handler. This is necessary because client POST
522 523 * request may be for something outside of the normal printer-uri
523 524 * space.
524 525 */
525 526 { "*/*", ipp_handler },
526 527
527 528 { NULL, NULL }
528 529 };
529 530
530 531
531 532 module MODULE_VAR_EXPORT ipp_module = {
532 533 STANDARD_MODULE_STUFF,
533 534 NULL, /* module initializer */
534 535 create_ipp_dir_config, /* create per-dir config structures */
535 536 NULL, /* merge per-dir config structures */
536 537 NULL, /* create per-server config structures */
537 538 NULL, /* merge per-server config structures */
538 539 ipp_cmds, /* table of config file commands */
539 540 ipp_handlers, /* [#8] MIME-typed-dispatched handlers */
540 541 NULL, /* [#1] URI to filename translation */
541 542 NULL, /* [#4] validate user id from request */
542 543 NULL, /* [#5] check if the user is ok _here_ */
543 544 NULL, /* [#3] check access by host address */
544 545 NULL, /* [#6] determine MIME type */
545 546 NULL, /* [#7] pre-run fixups */
546 547 NULL, /* [#9] log a transaction */
547 548 NULL, /* [#2] header parser */
548 549 NULL, /* child_init */
549 550 NULL, /* child_exit */
550 551 NULL /* [#0] post read-request */
551 552 };
552 553 #endif
↓ open down ↓ |
140 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX