355b4669e025ff377602b6fc7caaf30dbc218371jacobs * CDDL HEADER START
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * The contents of this file are subject to the terms of the
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * Common Development and Distribution License (the "License").
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * You may not use this file except in compliance with the License.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * See the License for the specific language governing permissions
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * and limitations under the License.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * When distributing Covered Code, include this CDDL HEADER in each
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * If applicable, add the following below this CDDL HEADER, with the
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * fields enclosed by brackets "[]" replaced with your own identifying
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * information: Portions Copyright [yyyy] [name of copyright owner]
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * CDDL HEADER END
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * Use is subject to license terms.
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/* $Id: mod_ipp.c 149 2006-04-25 16:55:01Z njacobs $ */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * Internet Printing Protocol (IPP) module for Apache.
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross#endif /* APACHE2 */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#ifndef AP_INIT_TAKE1 /* Apache 2.X has this, but 1.3.X does not */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#define AP_INIT_NO_ARGS(directive, action, arg, where, mesg) \
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#define AP_INIT_TAKE1(directive, action, arg, where, mesg) \
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#define AP_INIT_TAKE2(directive, action, arg, where, mesg) \
355b4669e025ff377602b6fc7caaf30dbc218371jacobstypedef struct {
355b4669e025ff377602b6fc7caaf30dbc218371jacobsdump_buffer(FILE *fp, char *tag, char *buffer, int bytes)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fprintf(fp, "%s %d(0x%x) bytes\n", (tag ? tag : ""), bytes, bytes);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs while (j < 16) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fprintf(stderr, "read_data(0x%8.8x, 0x%8.8x, %d): %d",
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * This is taken from ap_discard_request_body(). The reason we can't
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * just use it in Apache 1.3 is that it does various timeout things we
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * don't want it to do. Apache 2.0 doesn't do that, so we can safely
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * use the normal function.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs i = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs } while (i > 0);
355b4669e025ff377602b6fc7caaf30dbc218371jacobsvoid _log_rerror(const char *file, int line, int level, request_rec *r,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs const char *fmt, ...)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * fill in the message. If the buffer is too small, allocate
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * one that is large enough and fill it in.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if ((size = vsnprintf(message, BUFSIZ, fmt, args)) >= BUFSIZ)
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross ap_log_rerror(file, line, level, APR_SUCCESS, r, message);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papi_attribute_t **request = NULL, **response = NULL;
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross const char *s;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* Really, IPP is all POST requests */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * An IPP request must have a MIME type of "application/ipp"
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * (RFC-2910, Section 4, page 19). If it doesn't match this
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * MIME type, we should decline the request and let someone else
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * try and handle it.
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross s = apr_table_get(r->headers_in, "Content-Type");
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross if ((s == NULL) || (strcasecmp(s, "application/ipp") != 0))
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* CHUNKED_DECHUNK might not work right for IPP? */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs ap_soft_timeout("ipp_module: read/reply request ", r);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* read the IPP request off the network */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs status = ipp_read_message(read_data, r, &request, IPP_TYPE_REQUEST);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papiAttributeListPrint(stderr, request, "request (%d) ", getpid());
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross s = ap_get_remote_host(r->connection, r->per_dir_config,
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross s = ap_get_remote_host(r->connection, r->per_dir_config,
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross "originating-host", (char *)s);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross char *host = (char *)apr_table_get(r->headers_in, "Host");
355b4669e025ff377602b6fc7caaf30dbc218371jacobs (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs config = ap_get_module_config(r->per_dir_config, &ipp_module);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs (void) papiAttributeListAddCollection(&request, PAPI_ATTR_EXCL,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * For Trusted Solaris, pass the fd number of the socket connection
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * to the backend so the it can be forwarded to the backend print
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * service to retrieve the sensativity label off of a multi-level
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * In Apache 2.4 and later, could use: ap_get_conn_socket()
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * Apache 2.2 uses ap_get_module_config() but that needs
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * &core_module, for .module_index (which is just zero).
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * Could either inline that with index zero, or declare
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * core_module here. Latter seems less evil.
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross sockfd = ap_bfileno(r->connection->client, B_RD);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* process the request */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs status = ipp_process_request(request, &response, read_data, r);
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross "request failed: %s\n", papiStatusString(status));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fprintf(stderr, "processing result: %s\n", papiStatusString(status));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papiAttributeListPrint(stderr, response, "response (%d) ", getpid());
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * If the client is using chunking and we have not yet received the
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * final "0" sized chunk, we need to discard any data that may
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * remain in the post request.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if ((r->read_chunked != 0) &&
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross (apr_table_get(r->headers_in, "Content-Length") == NULL))
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* write an IPP response back to the network */
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross "write failed: %s\n", papiStatusString(status));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fprintf(stderr, "write result: %s\n", papiStatusString(status));
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross "flush failed, response may not have been sent");
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*ARGSUSED1*/
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic void *
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross (void) ipp_configure_operation(&config->operations,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*ARGSUSED0*/
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic const char *
355b4669e025ff377602b6fc7caaf30dbc218371jacobsipp_conformance(cmd_parms *cmd, void *cfg, const char *arg)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs IPPListenerConfig *config = (IPPListenerConfig *)cfg;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs return ("unknown conformance, try (automatic/1.0/1.1)");
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*ARGSUSED0*/
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic const char *
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Rossipp_operation(cmd_parms *cmd, void *cfg, const char *op, const char *toggle)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs IPPListenerConfig *config = (IPPListenerConfig *)cfg;
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross status = ipp_configure_operation(&config->operations,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs return (gettext("internal error (invalid argument)"));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* NOTREACHED */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* return (gettext("contact your software vendor")); */
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic const char *
355b4669e025ff377602b6fc7caaf30dbc218371jacobsipp_default_user(cmd_parms *cmd, void *cfg, const char *arg)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs IPPListenerConfig *config = (IPPListenerConfig *)cfg;
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic const char *
355b4669e025ff377602b6fc7caaf30dbc218371jacobsipp_default_svc(cmd_parms *cmd, void *cfg, const char *arg)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs IPPListenerConfig *config = (IPPListenerConfig *)cfg;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*ARGSUSED0*/
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic const char *
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * Wait so we can attach with a debugger. Once attached,
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross * assign ipp_module_hang_sleeping = 0 and step through.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#endif /* DEBUG */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs AP_INIT_TAKE1("ipp-conformance", ipp_conformance, NULL, ACCESS_CONF,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs "IPP protocol conformance (loose/strict)"),
355b4669e025ff377602b6fc7caaf30dbc218371jacobs AP_INIT_TAKE2("ipp-operation", ipp_operation, NULL, ACCESS_CONF,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs "IPP protocol operations to enable/disable)"),
355b4669e025ff377602b6fc7caaf30dbc218371jacobs AP_INIT_TAKE1("ipp-default-user", ipp_default_user, NULL, ACCESS_CONF,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs "default user for various operations"),
355b4669e025ff377602b6fc7caaf30dbc218371jacobs AP_INIT_TAKE1("ipp-default-service", ipp_default_svc, NULL, ACCESS_CONF,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs "default service for various operations"),
355b4669e025ff377602b6fc7caaf30dbc218371jacobs AP_INIT_NO_ARGS("ipp-module-hang", ipp_module_hang, NULL, ACCESS_CONF,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs "hang the module until we can attach a debugger (no args)"),
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*ARGSUSED0*/
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic const char *
355b4669e025ff377602b6fc7caaf30dbc218371jacobs return ("ipp");
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*ARGSUSED0*/
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic unsigned short
355b4669e025ff377602b6fc7caaf30dbc218371jacobs return (631);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/* Dispatch list for API hooks */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*ARGSUSED0*/
355b4669e025ff377602b6fc7caaf30dbc218371jacobs static const char * const modules[] = { "mod_dir.c", NULL };
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* Need to make sure we don't get directory listings by accident */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs ap_hook_handler(ipp_handler, NULL, modules, APR_HOOK_MIDDLE);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs ap_hook_default_port(ipp_port, NULL, NULL, APR_HOOK_MIDDLE);
b0e753dd6a955fb2f10a0ce17d32bd33172e0400Gordon Ross ap_hook_http_scheme(ipp_scheme, NULL, NULL, APR_HOOK_MIDDLE);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#else /* Apache 1.X */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/* Dispatch list of content handlers */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * This handler association causes all IPP request with the
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * correct MIME type to call the protocol handler.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * This hander association is causes everything to go through the IPP
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * protocol request handler. This is necessary because client POST
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * request may be for something outside of the normal printer-uri
355b4669e025ff377602b6fc7caaf30dbc218371jacobs create_ipp_dir_config, /* create per-dir config structures */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs ipp_handlers, /* [#8] MIME-typed-dispatched handlers */