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