httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From is...@apache.org
Subject svn commit: r651222 [1/2] - in /httpd/sandbox/mod_domain: LICENSE NOTICE README buckets.c errors.c mod_dns.c mod_dns.h protocol.c rr.h rr/ rr/rr.c rr/rr_a.c rr/rr_cname.c rr/rr_mx.c
Date Thu, 24 Apr 2008 11:45:09 GMT
Author: issac
Date: Thu Apr 24 04:44:55 2008
New Revision: 651222

URL: http://svn.apache.org/viewvc?rev=651222&view=rev
Log:
Initial import of mod_dns (which will likely be renamed mod_domain)  This is the exact copy which was licensed by NetmaskIt! (the original copyright holder) to be donated to the ASF (see http://www.mail-archive.com/dev@httpd.apache.org/msg38687.html)

This version is fully functional in TCP mode.  Rudimentry UDP support can be enabled for httpd-prefork/apr/apr-util using the patchset at http://mail-archives.apache.org/mod_mbox/apr-dev/200709.mbox/%3C46DE8285.2010707@beamartyr.net%3E

Added:
    httpd/sandbox/mod_domain/LICENSE
    httpd/sandbox/mod_domain/NOTICE
    httpd/sandbox/mod_domain/README
    httpd/sandbox/mod_domain/buckets.c
    httpd/sandbox/mod_domain/errors.c
    httpd/sandbox/mod_domain/mod_dns.c
    httpd/sandbox/mod_domain/mod_dns.h
    httpd/sandbox/mod_domain/protocol.c
    httpd/sandbox/mod_domain/rr/
    httpd/sandbox/mod_domain/rr.h
    httpd/sandbox/mod_domain/rr/rr.c
    httpd/sandbox/mod_domain/rr/rr_a.c
    httpd/sandbox/mod_domain/rr/rr_cname.c
    httpd/sandbox/mod_domain/rr/rr_mx.c

Added: httpd/sandbox/mod_domain/LICENSE
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_domain/LICENSE?rev=651222&view=auto
==============================================================================
--- httpd/sandbox/mod_domain/LICENSE (added)
+++ httpd/sandbox/mod_domain/LICENSE Thu Apr 24 04:44:55 2008
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

Added: httpd/sandbox/mod_domain/NOTICE
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_domain/NOTICE?rev=651222&view=auto
==============================================================================
--- httpd/sandbox/mod_domain/NOTICE (added)
+++ httpd/sandbox/mod_domain/NOTICE Thu Apr 24 04:44:55 2008
@@ -0,0 +1,5 @@
+Apache mod_domain
+Copyright (c) 2008 The Apache Software Foundation
+
+Original Copyright (c) Netmask.IT!® 2006-2007
+

Added: httpd/sandbox/mod_domain/README
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_domain/README?rev=651222&view=auto
==============================================================================
--- httpd/sandbox/mod_domain/README (added)
+++ httpd/sandbox/mod_domain/README Thu Apr 24 04:44:55 2008
@@ -0,0 +1,7 @@
+DNS Protocol module for The Apache HTTP Server 2.2
+
+Build as follows:
+
+apxs -cia mod_dns.c protocol.c errors.c buckets.c rr/*.c
+
+Enjoy :)
\ No newline at end of file

Added: httpd/sandbox/mod_domain/buckets.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_domain/buckets.c?rev=651222&view=auto
==============================================================================
--- httpd/sandbox/mod_domain/buckets.c (added)
+++ httpd/sandbox/mod_domain/buckets.c Thu Apr 24 04:44:55 2008
@@ -0,0 +1,146 @@
+/* Copyright 1999-2007 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Original Copyright (c) Netmask.IT!® 2006-2007
+ *
+ * DNS Protocol module for Apache 2.x
+ */
+
+#include "mod_dns.h"
+
+/** We need 4 bucket types: 3 for sending RRs (answer, authority, additional)
+ *  which will just be pool buckets that can identify themselves later, and
+ *  a 4th error type (we might steal normal apache error bucket for that)
+ */
+
+/** TODO: Currently, we ensure that the rr is transported correctly, but don't
+ *  consider sub-allocated memory, like rr->name, rr->rdata (and fields inside
+ *  rr->rdata).  We might want to serialize the rr in bucket_make and
+ *  unserialize it in bucket_read to guarantee it never disappears */
+
+static void dns_rr_bucket_destroy(void *data)
+{
+    apr_bucket_type_pool.destroy(data);
+}
+
+static
+/** This should read out rr->name, rr->rdata from some other form... */
+apr_status_t dns_rr_bucket_read(apr_bucket *e, const char **str,
+                               apr_size_t *len, apr_read_type_e block)
+{
+    return apr_bucket_type_pool.read(e, str, len, block);
+}
+
+/** This needs to be improved to setaside subpools (rr->name, rr->rdata, etc) */
+static
+apr_status_t dns_rr_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool)
+{
+    return apr_bucket_type_pool.setaside(data, reqpool);
+}
+
+static
+apr_status_t dns_rr_bucket_split(apr_bucket *a, apr_size_t point)
+{
+    return apr_bucket_type_pool.split(a, point);
+}
+
+static
+apr_status_t dns_rr_bucket_copy(apr_bucket *e, apr_bucket **c)
+{
+    return apr_bucket_type_pool.copy(e, c);
+}
+
+DNS_DECLARE_DATA const apr_bucket_type_t dns_rr_answer_bucket_type = {
+    "DNS_RR_ANSWER", 5, APR_BUCKET_DATA,
+    dns_rr_bucket_destroy,
+    dns_rr_bucket_read,
+    dns_rr_bucket_setaside,
+    dns_rr_bucket_split,
+    dns_rr_bucket_copy,
+};
+
+DNS_DECLARE_DATA const apr_bucket_type_t dns_rr_authority_bucket_type = {
+    "DNS_RR_AUTHORITY", 5, APR_BUCKET_DATA,
+    dns_rr_bucket_destroy,
+    dns_rr_bucket_read,
+    dns_rr_bucket_setaside,
+    dns_rr_bucket_split,
+    dns_rr_bucket_copy,
+};
+
+DNS_DECLARE_DATA const apr_bucket_type_t dns_rr_additional_bucket_type = {
+    "DNS_RR_ADDITIONAL", 5, APR_BUCKET_DATA,
+    dns_rr_bucket_destroy,
+    dns_rr_bucket_read,
+    dns_rr_bucket_setaside,
+    dns_rr_bucket_split,
+    dns_rr_bucket_copy,
+};
+
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_answer_create (
+                           const char *buf, apr_size_t length,
+                           apr_pool_t *pool, apr_bucket_alloc_t *list)
+{
+    apr_bucket *e = apr_bucket_pool_create(buf, length, pool, list);
+    e->type = &dns_rr_answer_bucket_type;
+    return e;
+}
+
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_answer_make (
+                           apr_bucket *b, const char *buf,
+                           apr_size_t length, apr_pool_t *pool)
+{
+    apr_bucket *e = apr_bucket_pool_make(b, buf, length, pool);
+    e->type = &dns_rr_answer_bucket_type;
+    return e;
+}
+
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_authority_create (
+                           const char *buf, apr_size_t length,
+                           apr_pool_t *pool, apr_bucket_alloc_t *list)
+{
+    apr_bucket *e = apr_bucket_pool_create(buf, length, pool, list);
+    e->type = &dns_rr_authority_bucket_type;
+    return e;
+}
+
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_authority_make (
+                           apr_bucket *b, const char *buf,
+                           apr_size_t length, apr_pool_t *pool)
+{
+    apr_bucket *e = apr_bucket_pool_make(b, buf, length, pool);
+    e->type = &dns_rr_authority_bucket_type;
+    return e;
+}
+
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_additional_create (
+                           const char *buf, apr_size_t length,
+                           apr_pool_t *pool, apr_bucket_alloc_t *list)
+{
+    apr_bucket *e = apr_bucket_pool_create(buf, length, pool, list);
+    e->type = &dns_rr_additional_bucket_type;
+    return e;
+}
+
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_additional_make (
+                           apr_bucket *b, const char *buf,
+                           apr_size_t length, apr_pool_t *pool)
+{
+    apr_bucket *e = apr_bucket_pool_make(b, buf, length, pool);
+    e->type = &dns_rr_additional_bucket_type;
+    return e;
+}

Added: httpd/sandbox/mod_domain/errors.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_domain/errors.c?rev=651222&view=auto
==============================================================================
--- httpd/sandbox/mod_domain/errors.c (added)
+++ httpd/sandbox/mod_domain/errors.c Thu Apr 24 04:44:55 2008
@@ -0,0 +1,85 @@
+/* Copyright 1999-2007 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Original Copyright (c) Netmask.IT!® 2006-2007
+ *
+ * DNS Protocol module for Apache 2.x
+ */
+
+#include "mod_dns.h"
+
+DNS_DECLARE(char *) dns_get_name_type(dns_type_t type)
+{
+    switch (type) {
+    case DNS_TYPE_A:
+        return "A";
+    case DNS_TYPE_NS:
+        return "NS";
+    case DNS_TYPE_MD:
+        return "MD";
+    case DNS_TYPE_MF:
+        return "MF";
+    case DNS_TYPE_CNAME:
+        return "CNAME";
+    case DNS_TYPE_SOA:
+        return "SOA";
+    case DNS_TYPE_MB:
+        return "MG";
+    case DNS_TYPE_MR:
+        return "MR";
+    case DNS_TYPE_NULL:
+        return "NULL";
+    case DNS_TYPE_WKS:
+        return "WKS";
+    case DNS_TYPE_PTR:
+        return "HINFO";
+    case DNS_TYPE_MINFO:
+        return "MINFO";
+    case DNS_TYPE_MX:
+        return "MX";
+    case DNS_TYPE_TXT:
+        return "TXT";
+    case DNS_QTYPE_AXFR:
+        return "AXFR";
+    case DNS_QTYPE_MAILA:
+        return "MAILA";
+    case DNS_QTYPE_MAILB:
+        return "MAILB";
+    case DNS_QTYPE_ALL:
+        return "*";
+    default:
+        return "INVALID";
+    }
+}
+
+DNS_DECLARE(char *) dns_get_name_class(dns_class_t type)
+{
+    switch (type) {
+    case DNS_CLASS_IN:
+        return "IN";
+    case DNS_CLASS_CS:
+        return "CS";
+    case DNS_CLASS_CH:
+        return "CH";
+    case DNS_CLASS_HS:
+        return "HS";
+    case DNS_QCLASS_ALL:
+        return "*";
+    default:
+        return "INVALID";
+    }
+}

Added: httpd/sandbox/mod_domain/mod_dns.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_domain/mod_dns.c?rev=651222&view=auto
==============================================================================
--- httpd/sandbox/mod_domain/mod_dns.c (added)
+++ httpd/sandbox/mod_domain/mod_dns.c Thu Apr 24 04:44:55 2008
@@ -0,0 +1,763 @@
+/* Copyright 1999-2007 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Original Copyright (c) Netmask.IT!® 2006-2007
+ *
+ * DNS Protocol module for Apache 2.x
+ */
+
+
+/* TODO LIST:
+ ** filters for compression (RFC 1035)
+ ** output truncation filter (limit UDP to 512 + set TC bit)
+ ** forward queries (*via tcp / * via udp with retransmission policy)
+ ** support AXFR queries for slaves to update from us
+ ** How should we update the scoreboard?  we use many logical reads/writes
+ ** query cache via mod_cache with special key_generator
+ ** Error support dns_die()
+ ** IPV6 Support?
+ ** Wildcard virtualhosts will return 0.0.0.0 as the IP.  What do we do with this?
+ */
+
+#include "mod_dns.h"
+
+static server_rec *base_server;
+
+APR_HOOK_STRUCT(
+    APR_HOOK_LINK(post_read_request)
+    APR_HOOK_LINK(handler)
+)
+
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(dns, DNS, int, post_read_request,
+                                    (dns_message_t *dns),
+                                    (dns),
+                                    OK, DECLINED)
+
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(dns, DNS, int, handler,
+                                    (request_rec *r),
+                                    (r), DECLINED)
+
+/** Be nice and export so other modules can remove it if they really want */
+DNS_DECLARE_DATA ap_filter_rec_t* dns_buffered_write_response_filter_handle;
+DNS_DECLARE_DATA ap_filter_rec_t* dns_buffered_write_proto_filter_handle;
+DNS_DECLARE_DATA ap_filter_rec_t* dns_output_protocol_filter_handle;
+DNS_DECLARE_DATA ap_filter_rec_t* dns_tcp_length_filter_handle;
+
+/** This isn't exported by core, so we need to redo ourselves... */
+DNS_DECLARE(int) dns_invoke_filter_init(ap_filter_t *filters)
+{
+    while (filters) {
+        if (filters->frec->filter_init_func) {
+            int result = filters->frec->filter_init_func(filters);
+            if (result != OK) {
+                return result;
+            }
+        }
+        filters = filters->next;
+    }
+    return OK;
+}
+
+DNS_DECLARE(request_rec *) dns_create_request(dns_message_t *dns) {
+    request_rec *r;
+    apr_pool_t *p;
+
+    apr_pool_create(&p, dns->pool);
+    apr_pool_tag(p, "request");
+    r = apr_pcalloc(p, sizeof(*r));
+    r->pool            = p;
+    r->connection      = dns->conn;
+    r->server          = dns->conn->base_server;
+
+    r->user            = NULL;
+    r->ap_auth_type    = NULL;
+    r->next            = NULL;
+    r->prev            = NULL;
+    r->main            = NULL;
+
+    r->allowed_methods = ap_make_method_list(p, 2);
+
+    r->headers_in      = apr_table_make(r->pool, 1);
+    r->subprocess_env  = apr_table_make(r->pool, 1);
+    r->headers_out     = apr_table_make(r->pool, 1);
+    r->err_headers_out = apr_table_make(r->pool, 1);
+    r->notes           = apr_table_make(r->pool, 5);
+
+    r->request_config  = ap_create_request_config(r->pool);
+    /* Must be set before we run create request hook */
+
+    r->proto_output_filters = dns->filters_out;
+    r->output_filters  = r->proto_output_filters;
+    r->proto_input_filters = dns->filters_in;
+    r->input_filters   = r->proto_input_filters;
+    r->per_dir_config  = r->server->lookup_defaults;
+
+    r->sent_bodyct     = 0;                      /* bytect isn't for body */
+
+    r->read_body       = REQUEST_NO_BODY;
+    r->handler         = NULL;
+
+    r->status          = HTTP_OK;  /* Until we get a request */
+    r->status_line     = NULL;
+    r->the_request     = NULL;
+
+    /* Begin by presuming any module can make its own path_info assumptions,
+     * until some module interjects and changes the value.
+     */
+    r->used_path_info = AP_REQ_DEFAULT_PATH_INFO;
+
+    ap_set_module_config(r->request_config, &dns_module, dns);
+    /** Cheat here and add our buffered write filter before anyone
+     *  else gets in the way */
+    ap_add_output_filter_handle(dns_buffered_write_response_filter_handle, NULL,
+                                r, dns->conn);
+
+    /** Let other modules do what they need now */
+    ap_run_create_request(r);
+    return r;
+}
+
+/** Our buffered output filter */
+typedef struct {
+    apr_bucket_brigade *bb;
+    int seen_eos;
+} dns_buffered_write_filter_ctx;
+
+static apr_status_t dns_buffered_write_filter(ap_filter_t *f,
+                                              apr_bucket_brigade *bb)
+{
+    dns_buffered_write_filter_ctx *ctx = f->ctx;
+    apr_bucket *b;
+    apr_off_t len = 0;
+    apr_status_t rv;
+
+    if (ctx == NULL) {
+        f->ctx = ctx = apr_palloc(f->r->pool, sizeof(*ctx));
+        ctx->bb = apr_brigade_create(f->r->pool,
+                                     f->r->connection->bucket_alloc);
+        ctx->seen_eos = 0;
+    }
+
+    if (ctx->seen_eos)
+        return APR_SUCCESS;
+
+    rv = APR_SUCCESS;
+
+    /** Buffer until we get a EOS or FLUSH */
+    for (b = APR_BRIGADE_FIRST(bb);
+         b != APR_BRIGADE_SENTINEL(bb) && !APR_BRIGADE_EMPTY(bb);
+         b = APR_BUCKET_NEXT(b))
+    {
+        APR_BUCKET_REMOVE(b);
+        APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
+        apr_brigade_length(ctx->bb, 1, &len);
+        if ((APR_BUCKET_IS_EOS(b) || APR_BUCKET_IS_FLUSH(b)) ||
+            (len > APR_BUCKET_BUFF_SIZE))
+        {
+            rv = ap_pass_brigade(f->next, ctx->bb);
+            apr_brigade_cleanup(ctx->bb);
+            if (APR_BUCKET_IS_EOS(b))
+                ctx->seen_eos = 1;
+        }
+    }
+
+    /** Give an empty brigade back */
+    apr_brigade_cleanup(bb);
+
+    /** if we got the EOS before the brigade ended, replace the unsent data */
+    if (ctx->seen_eos) {
+        APR_BRIGADE_CONCAT(bb, ctx->bb);
+        apr_brigade_destroy(ctx->bb);
+    }
+
+    return rv;
+}
+
+/** Our protocol output filter */
+static apr_status_t dns_output_protocol_filter(ap_filter_t *f,
+                                               apr_bucket_brigade *bb)
+{
+
+    dns_message_t *dns;
+    apr_bucket *b;
+    apr_size_t len = 0;
+    apr_status_t rv;
+    dns_rr_t *rr, *tmp_rr;
+    const char *data;
+    char *response;
+    apr_bucket_brigade *bb_out;
+
+    /*if (AP_BUCKET_IS_ERROR(e)) {
+            ap_bucket_error *eb = e->data;
+
+            ap_die(eb->status, r);
+            return AP_FILTER_ERROR;
+        }*/
+    /** Get our DNS message */
+    dns = (dns_message_t *)ap_get_module_config(f->r->request_config,
+                                                &dns_module);
+
+    if (!(dns)) {
+        ap_remove_output_filter(f);
+        return ap_pass_brigade(f->next, bb);
+    }
+
+    rv = APR_SUCCESS;
+
+    /** We can't flush and EOS means end of answer; we send content onward
+     *  when we've got all of our answers */
+    for (b = APR_BRIGADE_FIRST(bb);
+         b != APR_BRIGADE_SENTINEL(bb) && !APR_BRIGADE_EMPTY(bb);
+         b = APR_BUCKET_NEXT(b))
+    {
+        if (BUCKET_IS_DNS_RR(b)) {
+            /** Got an RR */
+            if (BUCKET_IS_DNS_ANSWER(b)) {
+                rr = apr_array_push(dns->answer);
+                dns->header->ancount++;
+            }
+            else if (BUCKET_IS_DNS_AUTHORITY(b)) {
+                rr = apr_array_push(dns->authority);
+                dns->header->nscount++;
+            }
+            else if (BUCKET_IS_DNS_ADDITIONAL(b)) {
+                rr = apr_array_push(dns->additional);
+                dns->header->arcount++;
+            }
+            else
+                rr = NULL;
+
+            rv = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
+            /** This is a waste of memory, but unserialize (correctly)
+             *  allocates a new rr, and apr_array_push will lose it's
+             *  pointer...  Since we can't play with the array's
+             *  pointers (why not?) we copy the block of memory */
+            dns_rr_unserialize(f->r->pool, data, &tmp_rr);
+            memcpy(rr, tmp_rr, sizeof(*rr));
+            apr_bucket_delete(b);
+            /** Handle errors */
+
+            continue;
+        }
+
+        if (APR_BUCKET_IS_EOS(b)) {
+            /** End of query - ignore everything after this */
+            apr_brigade_cleanup(bb);
+            dns->answered++;
+            break;
+        }
+
+        if (APR_BUCKET_IS_FLUSH(b)) {
+            /** We can't flush before we've assembled the response - sorry */
+            apr_bucket_delete(b);
+            continue;
+        }
+
+        /** Handle error buckets */
+
+        /** We don't know what to do with anything else... */
+        apr_bucket_delete(b);
+    }
+
+    if (dns->answered == dns->header->qdcount) {
+        /** We've assembled a response - send it out */
+        bb_out = apr_brigade_create(dns->pool, dns->conn->bucket_alloc);
+        rv = dns_write_response(dns, &response, &len);
+        b = apr_bucket_heap_create(response, len, free,
+                                   bb_out->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb_out, b);
+        /** Add flush (UDP needs this push) */
+        b = apr_bucket_flush_create(bb_out->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb_out, b);
+        /** Add EOS */
+        b = apr_bucket_eos_create(bb_out->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb_out, b);
+        /** Send it on its merry way */
+        rv = ap_pass_brigade(f->next, bb_out);
+        /** Core-output will destroy this brigade for us */
+    }
+    return rv;
+}
+
+/** TCP set-length filter - we cheat now by assuming one brigade holds
+ *  everything; it almost certainly does, but that's besides the point */
+static apr_status_t dns_tcp_length_filter(ap_filter_t *f,
+                                          apr_bucket_brigade *bb)
+{
+    apr_bucket *b;
+    apr_uint16_t len = 0;
+    apr_status_t rv;
+    int sd_type;
+
+    /** If we have a TCP connection, we'll need to write length */
+    apr_socket_type_get(ap_get_module_config(f->r->connection->conn_config,
+                                             &core_module),
+                        &sd_type);
+    if (sd_type == SOCK_STREAM) {
+        apr_brigade_length(bb, 1, (apr_off_t *)&len);
+        len = htons(len);
+
+        b = apr_bucket_transient_create((const char *)&len, 2, bb->bucket_alloc);
+        APR_BRIGADE_INSERT_HEAD(bb, b);
+    }
+
+    rv = ap_pass_brigade(f->next, bb);
+
+    /** We've done our work (and don't want to risk screwing more up) */
+    ap_remove_output_filter(f);
+
+    return rv;
+}
+
+static void finalize_response(request_rec *r) {
+    apr_bucket_brigade *bb;
+    apr_bucket *b;
+
+    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+    b = apr_bucket_eos_create(bb->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(bb, b);
+    ap_pass_brigade(r->output_filters, bb);
+    apr_brigade_destroy(bb);
+}
+
+static int process_dns_connection(conn_rec *c)
+{
+    dns_module_config_t *conf;
+    dns_message_t *dns;
+    dns_query_t *q;
+    request_rec *r;
+    server_rec *s = c->base_server;
+    apr_status_t rv;
+    int access_status;
+    int i;
+
+    conf = (dns_module_config_t *)ap_get_module_config(s->module_config,
+                                                       &dns_module);
+    if (!conf) {
+        /* We're not configured.  Something's very wrong. Abort. */
+        return DECLINED;
+    }
+
+    if (!conf->enabled) {
+        /* We're configured, but disabled */
+        return DECLINED;
+    }
+    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0,c, "I got a connection!");
+
+    dns = dns_read_message_header(c);
+
+    if (!(dns)) {
+        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, "[mod_dns] Unable to read "
+                      "DNS message header.  Aborting.");
+        return OK;
+    }
+
+    dns_run_post_read_request(dns);
+    for (i=0;i<dns->header->qdcount;i++) {
+        q = NULL;
+        r = NULL;
+        rv = dns_read_request(dns, &r, &q);
+        if (rv != APR_SUCCESS) {
+            /* Set header->rcode to error and abort */
+            /* dns_die should read remaining bytes from socket,
+             * set error in dns_header_t, write response, and return
+             */
+        } else {
+            /** Allow mod_cache to act as our resolver cache */
+            access_status = ap_run_quick_handler(r, 0);
+                if (access_status == DECLINED) {
+                    access_status = ap_process_request_internal(r);
+                    if (access_status != OK) {
+                        /** Handle me */
+                    }
+                    /** Invoke handler (return response) */
+                    access_status = dns_invoke_filter_init(r->output_filters);
+                    if (access_status != OK)
+                        /** Log, but continue */
+                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, access_status,
+                                      r, "[mod_dns] Error initializing "
+                                      "output filters for %s",
+                                      r->the_request);
+
+                    /** Run handler - only DNS registered handlers
+                      * to avoid default-handler */
+                    access_status = dns_run_handler(r);
+                    finalize_response(r);
+
+                    if (access_status == DECLINED) {
+                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                            "[mod_dns] handler not found for method \"%s\"",
+                            r->handler, r->method);
+                        /** die */
+                    }
+                }
+            if (access_status == DONE) {
+                /* e.g., something not in storage like TRACE */
+                access_status = OK;
+            }
+
+            if (access_status != OK) {
+                /** Return error (dns_die)*/
+            } else {
+                /** Cleanup */
+            }
+
+            /* FIXME:
+             * Suppose that the logging causes a DNS lookup to occur, which may
+             * have a high latency.  If we hold off on this packet, then it'll
+             * appear like the link is stalled when really it's the application
+             * that's stalled.
+             * Since we can't send packets until all queries in the message
+             * are answered, we should add the request_rec to a list and
+             * batch-log them later
+             */
+            ap_run_log_transaction(r);
+        }
+    }
+    /** Flush response */
+    /** Log + cleanup */
+    return OK;
+}
+
+/* -------------------------------------------------------------- */
+/* Default handlers */
+
+static server_rec *matches_aliases(server_rec *s, const char *host)
+{
+    int i;
+    apr_array_header_t *names;
+
+    while (s) {
+        /* match ServerName */
+        if (!strcasecmp(host, s->server_hostname)) {
+            return s;
+        }
+
+        /* search all the aliases from ServerAlias directive */
+        names = s->names;
+        if (names) {
+            char **name = (char **) names->elts;
+            for (i = 0; i < names->nelts; ++i) {
+                if(!name[i]) continue;
+                if (!strcasecmp(host, name[i]))
+                    return s;
+            }
+        }
+        names = s->wild_names;
+        if (names) {
+            char **name = (char **) names->elts;
+            for (i = 0; i < names->nelts; ++i) {
+                if(!name[i]) continue;
+                if (!ap_strcasecmp_match(host, name[i]))
+                    return s;
+            }
+        }
+        s = s->next;
+    }
+    return NULL;
+}
+
+static int dns_default_handler(request_rec *r) {
+    dns_rr_t* rr;
+    dns_rdata_a_t *a;
+    server_rec *s;
+    char *name;
+
+    if (strcasecmp(r->handler, DNS_MAGIC_TYPE))
+        return DECLINED;
+    if (strcasecmp(r->method, "A"))
+        return DECLINED;
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                  "Running A/CNAME lookup for host %s", r->hostname);
+
+    if ((s = matches_aliases(base_server, r->hostname)) == NULL)
+        return DECLINED;
+
+    name = (char *)r->hostname;
+    if (strcasecmp(s->server_hostname, r->hostname)) {
+        dns_rdata_cname_t *cname;
+        /** Add CNAME */
+        cname = apr_palloc(r->pool, sizeof(*cname));
+        cname->cname = apr_pstrdup(r->pool, s->server_hostname);
+        rr = dns_create_rr(r, r->hostname, DNS_TYPE_CNAME, DNS_CLASS_IN, 0);
+        rr->rdata->rdata = cname;
+        dns_add_rr_answer(r, rr);
+        name = s->server_hostname;
+    }
+    /** Add A */
+    a = apr_pcalloc(r->pool, sizeof(*a));
+    a->address = inet_addr(inet_ntoa(*((struct in_addr *)s->addrs->host_addr->ipaddr_ptr)));
+    /** We get network address in network order; since serialize expects it in
+     *  host order, switch here.*/
+    a->address = ntohl(a->address);
+    rr = dns_create_rr(r, name, DNS_TYPE_A, DNS_CLASS_IN, 0);
+    rr->rdata->rdata = a;
+    dns_add_rr_answer(r, rr);
+    return OK;
+}
+
+static int dns_mx_handler(request_rec *r) {
+    dns_module_config_t *conf;
+    dns_rr_t* rr;
+    dns_rdata_mx_t *mx;
+    apr_array_header_t *mxs;
+    server_rec *s;
+    char *name;
+
+    if (strcasecmp(r->handler, DNS_MAGIC_TYPE))
+        return DECLINED;
+    if (strcasecmp(r->method, "MX"))
+        return DECLINED;
+
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+              "Running MX lookup for host %s", r->hostname);
+
+    if ((s = matches_aliases(base_server, r->hostname)) == NULL)
+        return DECLINED;
+
+    name = (char *)r->hostname;
+    if (strcasecmp(s->server_hostname, r->hostname))
+        return DECLINED; /* Require exact match here */
+
+    conf =
+      (dns_module_config_t *)ap_get_module_config(s->module_config,
+                                                  &dns_module);
+
+    if (!(conf->mx))
+        return DECLINED;
+
+    mxs = apr_array_copy(r->pool, conf->mx);
+
+    while (!(apr_is_empty_array(mxs))) {
+        mx = apr_array_pop(mxs);
+        rr = dns_create_rr(r, r->hostname, DNS_TYPE_MX, DNS_CLASS_IN, 0);
+        rr->rdata->rdata = mx;
+        dns_add_rr_answer(r, rr);
+    }
+    return OK;
+}
+
+static int ap_create_request_handler(request_rec *r) {
+    dns_message_t *dns;
+
+    dns = (dns_message_t *)ap_get_module_config(r->request_config,
+                                                &dns_module);
+
+    if (!(dns))
+        return DECLINED;
+
+    ap_add_output_filter_handle(dns_output_protocol_filter_handle, NULL,
+                                r, dns->conn);
+/*    ap_add_output_filter_handle(dns_buffered_write_proto_filter_handle, NULL,
+                                r, dns->conn);*/
+    ap_add_output_filter_handle(dns_tcp_length_filter_handle, NULL,
+                                r, dns->conn);
+
+    /** Don't care what this is, as long as it's not OK,  We do it to prevent
+     *  default HTTP protocol handlers from registering */
+    return DECLINED * 2;
+}
+
+static int dns_post_read_request(dns_message_t *dns) {
+    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, dns->conn,
+                  "I got %d queries in the message", dns->header->qdcount);
+    return OK;
+}
+
+static int dns_post_config(apr_pool_t *p, apr_pool_t *plog,
+                           apr_pool_t *ptemp, server_rec *s)
+{
+    base_server = s;
+    dns_register_rr((dns_rdata_t *)&dns_rdata_a, DNS_TYPE_A);
+    dns_register_rr((dns_rdata_t *)&dns_rdata_cname, DNS_TYPE_CNAME);
+    dns_register_rr((dns_rdata_t *)&dns_rdata_mx, DNS_TYPE_MX);
+    return OK;
+}
+
+
+
+/* -------------------------------------------------------------- */
+/* Setup configurable data */
+
+static void *create_dns_config(apr_pool_t *p, server_rec *s)
+{
+    dns_module_config_t *ps = apr_pcalloc(p, sizeof(*ps));
+    ps->enabled = 0;
+    ps->enabled_set = 0;
+    ps->default_ttl = DEFAULT_DEFAULT_TTL;
+    ps->default_ttl_set = 0;
+    ps->mx = NULL;
+    return ps;
+}
+
+static void *merge_dns_config(apr_pool_t *p, void *basev, void *overridesv)
+{
+    dns_module_config_t *ps = apr_pcalloc(p, sizeof(*ps));
+    dns_module_config_t *base = (dns_module_config_t *) basev;
+    dns_module_config_t *overrides = (dns_module_config_t *) overridesv;
+
+    ps->enabled =
+        (overrides->enabled_set == 0)
+        ? base->enabled
+        : overrides->enabled;
+    ps->default_ttl =
+        (overrides->default_ttl_set == 0)
+        ? base->default_ttl
+        : overrides->default_ttl;
+
+    if (base->mx || overrides->mx) {
+        if (base->mx)
+            ps->mx = base->mx;
+        if (overrides->mx)
+            if (ps->mx) {
+                apr_array_cat(ps->mx, overrides->mx);
+            } else {
+                ps->mx = overrides->mx;
+            }
+    }
+
+
+    return ps;
+}
+
+static const char *set_dns_enabled(cmd_parms *parms, void *dummy, int flag)
+{
+    dns_module_config_t *conf;
+
+    const char *err = ap_check_cmd_context(parms,
+                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+    if (err) {
+        return err;
+    }
+
+    conf =
+      (dns_module_config_t *)ap_get_module_config(parms->server->module_config,
+                                                  &dns_module);
+    conf->enabled = flag;
+    conf->enabled_set = 1;
+    return NULL;
+}
+
+static const char *set_dns_default_ttl(cmd_parms *parms, void *dummy,
+                                       const char *arg)
+{
+    dns_module_config_t *conf;
+
+    const char *err = ap_check_cmd_context(parms, GLOBAL_ONLY);
+    if (err) {
+        return err;
+    }
+
+    conf =
+      (dns_module_config_t *)ap_get_module_config(parms->server->module_config,
+                                                  &dns_module);
+    conf->default_ttl = (apr_size_t) atol(arg);
+    conf->default_ttl_set = 1;
+    return NULL;
+}
+
+static const char *set_dns_add_mx(cmd_parms *parms, void *dummy,
+                                  const char *preference, const char *exchange)
+{
+    dns_module_config_t *conf;
+    dns_rdata_mx_t *mx;
+
+    const char *err = ap_check_cmd_context(parms, GLOBAL_ONLY);
+    if (err) {
+        return err;
+    }
+
+    conf =
+      (dns_module_config_t *)ap_get_module_config(parms->server->module_config,
+                                                  &dns_module);
+
+    if (!(conf->mx)) {
+        conf->mx = apr_array_make(parms->pool, 2, sizeof(dns_rdata_mx_t));
+        if (!(conf->mx))
+            return "Could not allocate list of MXs for virtualhost";
+    }
+
+    mx = apr_array_push(conf->mx);
+    if (!(mx))
+        return "Could not allocate MX";
+    mx->preference = (apr_uint16_t)apr_atoi64(preference);
+    mx->exchange = apr_pstrdup(parms->pool, exchange);
+
+    return NULL;
+}
+
+static const command_rec dns_cmds[] =
+{
+    AP_INIT_FLAG("DNSEnabled", set_dns_enabled, NULL, RSRC_CONF,
+                  "Enable the DNS server on this VirtualHost."),
+    AP_INIT_TAKE1("DNSDefaultTTL", set_dns_default_ttl, NULL, RSRC_CONF,
+                  "Sets the default TTL used for all DNS replies (defaults"
+                  "to 30 days"),
+    AP_INIT_TAKE2("DNSAddMX", set_dns_add_mx, NULL, RSRC_CONF,
+                  "Adds an MX record to the current domain"),
+    {NULL}
+};
+
+static void register_hooks(apr_pool_t *p)
+{
+    ap_hook_post_config(dns_post_config, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_process_connection(process_dns_connection, NULL, NULL, APR_HOOK_FIRST);
+    /** FIXME: We hook REALLY_LAST - 1 to prevent default HTTP protocol
+     *  handlers to be installed for the request, but there ought to be a
+     *  better way... */
+    ap_hook_create_request(ap_create_request_handler, NULL, NULL,
+                           APR_HOOK_REALLY_LAST - 1);
+    dns_hook_post_read_request(dns_post_read_request, NULL, NULL, APR_HOOK_MIDDLE);
+    /** Although we don't take care of everything, hook after last so 3rd party
+     *  handlers are always before us */
+    dns_hook_handler(dns_mx_handler, NULL, NULL, APR_HOOK_LAST + 4);
+    dns_hook_handler(dns_default_handler, NULL, NULL, APR_HOOK_LAST + 5);
+    /* Put buffered output filter as close as possible to front */
+    dns_buffered_write_response_filter_handle =
+        ap_register_output_filter_protocol("DNS_BUFFERED_WRITE",
+                                           dns_buffered_write_filter, NULL,
+                                           AP_FTYPE_RESOURCE, 0);
+    dns_output_protocol_filter_handle =
+        ap_register_output_filter_protocol("DNS_OUTPUT_PROTOCOL",
+                                           dns_output_protocol_filter, NULL,
+                                           AP_FTYPE_PROTOCOL,
+                                           AP_FILTER_PROTO_CHANGE +
+                                           AP_FILTER_PROTO_CHANGE_LENGTH +
+                                           AP_FILTER_PROTO_NO_BYTERANGE);
+    dns_buffered_write_proto_filter_handle =
+        ap_register_output_filter_protocol("DNS_BUFFERED_WRITE",
+                                           dns_buffered_write_filter, NULL,
+                                           AP_FTYPE_PROTOCOL, 0);
+    dns_tcp_length_filter_handle =
+        ap_register_output_filter_protocol("DNS_TCP_LENGTH",
+                                           dns_tcp_length_filter, NULL,
+                                           AP_FTYPE_PROTOCOL,
+                                           AP_FILTER_PROTO_CHANGE +
+                                           AP_FILTER_PROTO_CHANGE_LENGTH +
+                                           AP_FILTER_PROTO_NO_BYTERANGE);
+}
+
+/* Dispatch list for API hooks */
+module AP_MODULE_DECLARE_DATA dns_module = {
+    STANDARD20_MODULE_STUFF,
+    NULL,                  /* create per-dir    config structures */
+    NULL,                  /* merge  per-dir    config structures */
+    create_dns_config,     /* create per-server config structures */
+    merge_dns_config,      /* merge  per-server config structures */
+    dns_cmds,              /* table of config file commands       */
+    register_hooks         /* register hooks                      */
+};

Added: httpd/sandbox/mod_domain/mod_dns.h
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_domain/mod_dns.h?rev=651222&view=auto
==============================================================================
--- httpd/sandbox/mod_domain/mod_dns.h (added)
+++ httpd/sandbox/mod_domain/mod_dns.h Thu Apr 24 04:44:55 2008
@@ -0,0 +1,530 @@
+/* Copyright 1999-2007 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Original Copyright (c) Netmask.IT!® 2006-2007
+ *
+ * DNS Protocol module for Apache 2.x
+ */
+
+#ifndef MOD_DNS_H
+#define MOD_DNS_H
+
+#include "httpd.h"
+#define CORE_PRIVATE
+#include "util_filter.h"
+#include "apr.h"
+#include "apr_tables.h"
+#include "apr_hooks.h"
+#include "apr_pools.h"
+#include "apu.h"
+#include "apr_buckets.h"
+#include "ap_config.h"
+
+#include "http_protocol.h"
+#include "http_config.h"
+#include "http_connection.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_vhost.h"
+#include "scoreboard.h"
+#include "http_log.h"
+#include "apr_network_io.h"
+#include "apr_strings.h"
+#include "apr_uri.h"
+
+#define APR_WANT_BYTEF
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+#ifdef  __cplusplus
+ extern "C" {
+#endif
+
+#define DEFAULT_DEFAULT_TTL 2592000 /* 30 days */
+#define DNS_MAGIC_TYPE "apache/mod_dns_query"
+
+/* Create a set of DNS_DECLARE(type), DNS_DECLARE_NONSTD(type) and
+ * DNS_DECLARE_DATA with appropriate export and import tags for the platform
+ */
+#if !defined(WIN32)
+#define DNS_DECLARE(type)            type
+#define DNS_DECLARE_NONSTD(type)     type
+#define DNS_DECLARE_DATA
+#elif defined(DNS_DECLARE_STATIC)
+#define DNS_DECLARE(type)            type __stdcall
+#define DNS_DECLARE_NONSTD(type)     type
+#define DNS_DECLARE_DATA
+#elif defined(DNS_DECLARE_EXPORT)
+#define DNS_DECLARE(type)            __declspec(dllexport) type __stdcall
+#define DNS_DECLARE_NONSTD(type)     __declspec(dllexport) type
+#define DNS_DECLARE_DATA             __declspec(dllexport)
+#else
+#define DNS_DECLARE(type)            __declspec(dllimport) type __stdcall
+#define DNS_DECLARE_NONSTD(type)     __declspec(dllimport) type
+#define DNS_DECLARE_DATA             __declspec(dllimport)
+#endif
+
+/** mod_dns server config */
+
+module AP_MODULE_DECLARE_DATA dns_module;
+
+typedef struct {
+    int enabled;
+    int enabled_set;
+    apr_int32_t default_ttl;
+    int default_ttl_set;
+    apr_array_header_t *mx;
+} dns_module_config_t;
+
+/* generic payload type for RRs */
+typedef struct dns_rdata_t {
+    void *rdata;            /* Contains the rdata type */
+    apr_status_t (*serialize)(void *rdata, char *data, int *dlen);
+                            /* Serializing function which takes a pre-allocated
+                             * character array large enough to fit and serializes
+                             * the rdata structure into it.  dlen will return
+                             * the actual length of data on return.*/
+    apr_status_t (*pserialize)(void *rdata, apr_pool_t *pool, char **data,
+                               int *dlen);
+                            /* Similar to serialize, but will allocate memory
+                             * from pool as needed.  dlen will be data length
+                             * on return.*/
+    apr_status_t (*unserialize)(apr_pool_t *pool, const char *data,
+                                void **rdata);
+                            /* Unserialize data into an rdata struct allocated
+                             * from pool */
+} dns_rdata_t;
+
+/** DNS "TYPE" values */
+typedef enum {
+    DNS_TYPE_A        =   1, /* a host address */
+    DNS_TYPE_NS,             /* an authoritative name server */
+    DNS_TYPE_MD,             /* a mail destination (Obsolete - use MX) */
+    DNS_TYPE_MF,             /* a mail forwarder (Obsolete - use MX) */
+    DNS_TYPE_CNAME,          /* the canonical name for an alias */
+    DNS_TYPE_SOA,            /* marks the start of a zone of authority */
+    DNS_TYPE_MB,             /* a mailbox domain name (EXPERIMENTAL) */
+    DNS_TYPE_MG,             /* a mail group member (EXPERIMENTAL) */
+    DNS_TYPE_MR,             /* a mail rename domain name (EXPERIMENTAL) */
+    DNS_TYPE_NULL,           /* a null RR (EXPERIMENTAL) */
+    DNS_TYPE_WKS,            /* a well known service description */
+    DNS_TYPE_PTR,            /* a domain name pointer */
+    DNS_TYPE_HINFO,          /* host information */
+    DNS_TYPE_MINFO,          /* mailbox or mail list information */
+    DNS_TYPE_MX,             /* mail exchange */
+    DNS_TYPE_TXT,            /* text strings */
+    DNS_QTYPE_AXFR    = 252, /* A request for a transfer of an entire zone */
+    DNS_QTYPE_MAILB,         /* A request for mailbox-related records */
+    DNS_QTYPE_MAILA,         /* A request for mail agent RRs (Obsolete - see MX) */
+    DNS_QTYPE_ALL            /* A request for all records */
+} dns_type_t;
+
+/** DNS "CLASS" values */
+typedef enum {
+    DNS_CLASS_IN      =   1, /* The internet */
+    DNS_CLASS_CS,            /* The CSNET class (Obsolete) */
+    DNS_CLASS_CH,            /* The CHAOS class */
+    DNS_CLASS_HS,            /* Hesiod [Dyer 87] */
+    DNS_QCLASS_ALL    = 255  /* Any class */
+} dns_class_t;
+
+/** Generic flag (1-bit). */
+typedef enum {
+    DNS_FLAG_OFF    = 0,
+    DNS_FLAG_ON     = 1
+} dns_flag_t;
+
+/** DNS Opcode */
+typedef enum {
+    DNS_OPCODE_QUERY    = 0,
+    DNS_OPCODE_IQUERY   = 1,
+    DNS_OPCODE_STATUS   = 2,
+    DNS_OPCODE_RESERVED = 15
+} dns_opcode_t;
+
+/** DNS Response code */
+typedef enum {
+    DNS_SUCCESS         =  0,
+    DNS_EFORMAT         =  1,
+    DNS_ESERVER         =  2,
+    DNS_ENAME           =  3,
+    DNS_ENOIMPL         =  4,
+    DNS_EREFUSED        =  5,
+    DNS_ERESERVED       = 15,
+} dns_rcode_t;
+
+/* Query data type
+ * The question section is used to carry the "question" in most queries,
+ * i.e., the parameters that define what is being asked.  The section
+ * contains QDCOUNT (usually 1) entries, each of the following format:
+ *
+ *                                     1  1  1  1  1  1
+ *       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                                               |
+ *     /                     QNAME                     /
+ *     /                                               /
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                     QTYPE                     |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                     QCLASS                    |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+typedef struct {
+    char *qname;            /* a domain name represented as a sequence of
+                             * labels, where each label consists of a length
+                             * octet followed by that number of octets.
+                             * The domain name terminates with the zero length
+                             * octet for the null label of the root.  Note that
+                             * this field may be an odd number of octets; no
+                             * padding is used.*/
+    apr_uint16_t qtype;     /* a two octet code which specifies the type of the
+                             * query.  The values for this field include all
+                             * codes valid for a TYPE field, together with some
+                             * more general codes which can match more than one
+                             * type of RR.*/
+    apr_uint16_t qclass;    /* a two octet code that specifies the class of the
+                             * query.  For example, the QCLASS field is IN for
+                             * the Internet.*/
+} dns_query_t;
+
+/* RR data type
+ * All RRs have the same top level format shown below:
+ *
+ *                                     1  1  1  1  1  1
+ *       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                                               |
+ *     /                                               /
+ *     /                      NAME                     /
+ *     |                                               |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                      TYPE                     |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                     CLASS                     |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                      TTL                      |
+ *     |                                               |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                   RDLENGTH                    |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ *     /                     RDATA                     /
+ *     /                                               /
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+*/
+
+typedef struct {
+    char *name;             /* an owner name, i.e., the name of the node to
+                             * which this resource record pertains.*/
+    apr_uint16_t type;      /* two octets containing one of the RR TYPE codes.*/
+    apr_uint16_t classtype; /* two octets containing one of the RR CLASS codes.*/
+    apr_int32_t ttl;        /* a 32 bit signed integer that specifies the time
+                             * that the resource record may be cached before
+                             * the source interval of the information should
+                             * again be consulted.  Zero values are interpreted
+                             * to mean that the RR can only be used for the
+                             * transaction in progress, and should not be
+                             * cached.  For example, SOA records are always
+                             * distributed with a zero TTL to prohibit caching.
+                             * Zero values can also be used for extremely
+                             * volatile data.*/
+    apr_uint16_t rdlength;  /* an unsigned 16 bit integer that specifies the
+                             * length in octets of the RDATA field.*/
+    dns_rdata_t *rdata;     /* a variable length string of octets that describes
+                             * the resource.  The format of this information
+                             * varies according to the TYPE and CLASS of the
+                             * resource record.*/
+} dns_rr_t;
+
+/* rdata payloads */
+
+typedef struct {
+    char *cname;            /* A <domain-name> which specifies the canonical
+                             * or primary name for the owner.  The owner name
+                             * is an alias.*/
+} dns_rdata_cname_t;
+
+typedef struct {
+    apr_uint16_t preference;/* A 16 bit integer which specifies the preference
+                             * given to this RR among others at the same owner
+                             * Lower values are preferred.*/
+    char *exchange;         /* A <domain-name> which specifies a host willing
+                             * to act as a mail exchange for the owner name.*/
+} dns_rdata_mx_t;
+
+typedef struct {
+    char *nsdname;          /* A <domain-name> which specifies a host which
+                             * should be authoritative for the specified class
+                             * and domain.*/
+} dns_rdata_ns_t;
+
+
+typedef struct {
+    char *mname;            /* The <domain-name> of the name server that was the
+                             * original or primary source of data for this zone.*/
+    char *rname;            /* A <domain-name> which specifies the mailbox of
+                             * the person responsible for this zone.*/
+    apr_uint32_t serial;    /* The unsigned 32 bit version number of the
+                             * original copy of the zone.  Zone transfers
+                             * preserve this value. This value wraps and should
+                             * be compared using sequence space arithmetic.*/
+    apr_int32_t refresh;    /* A 32 bit time interval before the zone should be
+                             * refreshed.*/
+    apr_int32_t retry;      /* A 32 bit time interval that should elapse before
+                             * a failed refresh should be retried.*/
+    apr_int32_t expires;    /* A 32 bit time value that specifies the upper
+                             * limit on the time interval that can elapse
+                             * before the zone is no longer authoritative.*/
+    apr_uint32_t minimum;   /* The unsigned 32 bit minimum TTL field that should
+                               be exported with any RR from this zone.*/
+} dns_rdata_soa_t;
+
+typedef struct {
+    char *txtdata;          /* One or more <character-string>s.*/
+} dns_rdata_txt_t;
+
+typedef struct {
+    apr_uint32_t address;  /* A 32 bit Internet address */
+} dns_rdata_a_t;
+
+/* Message header data type
+ * The header contains the following fields:
+ *
+ *                                     1  1  1  1  1  1
+ *       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                      ID                       |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                    QDCOUNT                    |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                    ANCOUNT                    |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                    NSCOUNT                    |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *     |                    ARCOUNT                    |
+ *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+
+/** We'll use apr_byte_t for any field < 8 bytes */
+typedef struct {
+    apr_uint16_t id;       /* A 16 bit identifier assigned by the program that
+                            * generates any kind of query.  This identifier is
+                            * copied the corresponding reply and can be used by
+                            * the requester to match up replies to outstanding
+                            * queries.*/
+    dns_flag_t qr;         /* A one bit field that specifies whether this
+                            * message is a query (OFF), or a response (ON).*/
+    dns_opcode_t opcode;   /* A four bit field that specifies kind of query in
+                            * this  message.  This value is set by the
+                            * originator of a query and copied into the response
+                            * The values are:
+                            * DNS_OPCODE_QUERY       a standard query
+                            * DNS_OPCODE_IQUERY      an inverse query
+                            * DNS_OPCODE_STATUS      a server status request
+                            * DNS_OPCODE_RESERVED    reserved for future use*/
+    dns_flag_t aa;         /* Authoritative Answer - this bit is valid in
+                            * responses and specifies that the responding
+                            * name server is an authority for the domain name
+                            * in question section.
+                            * Note that the contents of the answer section may
+                            * have multiple owner names because of aliases.
+                            * The AA bit corresponds to the name which matches
+                            * the query name, or the first owner name in the
+                            * answer section.*/
+    dns_flag_t tc;         /* TrunCation - specifies that this message was
+                            * truncated due to length greater than that
+                            * permitted on the transmission channel.*/
+    dns_flag_t rd;         /* Recursion Desired - this bit may be set in a
+                            * query and is copied into the response.  If RD is
+                            * set, it directs the name server to pursue the
+                            * query recursively.  Recursive query support is
+                            * optional according to RFC 1035.*/
+    int        ra;         /* Recursion Available - this be is set or cleared
+                            * in a response, and denotes whether recursive
+                            * query support is available in the name server.*/
+    dns_flag_t z;          /* Reserved for future use.  Must be zero in all
+                            * queries and responses.*/
+    dns_rcode_t rcode;     /* Response code - this 4 bit field is set as part
+                            * of responses.  The values have the following
+                            * interpretation:
+                            * DNS_SUCCESS      No error condition
+                            * DNS_EFORMAT      Format error - The name server
+                            *                  was unable to interpret the query
+                            * DNS_ESERVER      The name server was unable to
+                            *                  process this query due to a
+                            *                  problem with the name server.
+                            * DNS_ENAME        Meaningful only for responses
+                            *                  from an authoritative name server
+                            *                  this code signifies that the
+                            *                  domain name referenced in the
+                            *                  query does not exist.
+                            * DNS_ENOIMPL      The name server does not support
+                            *                  the requested kind of query.
+                            * DNS_EREFUSED     The name server refuses to
+                            *                  perform the specified operation
+                            *                  for policy reasons.  For example
+                            *                  a name server may not wish to
+                            *                  provide the information to the
+                            *                  particular requester, or a name
+                            *                  server may not wish to perform
+                            *                  a particular operation (e.g.,
+                            *                  zone transfer) for particular
+                            *                  data.
+                            * DNS_ERESERVED    Reserved for future use.*/
+    apr_uint16_t qdcount;  /* an unsigned 16 bit integer specifying the number
+                            * of entries in the question section.*/
+    apr_uint16_t ancount;  /* an unsigned 16 bit integer specifying the number
+                            * of resource records in the answer section.*/
+    apr_uint16_t nscount;  /* an unsigned 16 bit integer specifying the number
+                            * of name server resource records in the authority
+                            * records section.*/
+    apr_uint16_t arcount;  /* an unsigned 16 bit integer specifying the number
+                            * of resource records in the additional records
+                            * section.*/
+} dns_header_t;
+
+/* DNS message
+ *
+ *     +---------------------+
+ *     |        Header       |
+ *     +---------------------+
+ *     |       Question      | the question for the name server
+ *     +---------------------+
+ *     |        Answer       | RRs answering the question
+ *     +---------------------+
+ *     |      Authority      | RRs pointing toward an authority
+ *     +---------------------+
+ *     |      Additional     | RRs holding additional information
+ *     +---------------------+
+ */
+typedef struct {
+    apr_pool_t         *pool;       /* Local pool */
+    conn_rec           *conn;       /* The underlying connection */
+    apr_uint16_t       length;      /* Length - UDP sets this to 0, and sets
+                                     * TC bit in headers if > 512 bytes */
+    apr_uint16_t       bytesread;   /* Bytes of message read so far */
+    int answered;                   /* Counter of answered queries so far */
+    ap_filter_t        *filters_in; /* Per-message input filters */
+    ap_filter_t        *filters_out;/* Per-message output filters */
+    dns_header_t       *header;
+    apr_array_header_t *query;
+    apr_array_header_t *answer;
+    apr_array_header_t *authority;
+    apr_array_header_t *additional;
+} dns_message_t;
+
+/** errors.c */
+DNS_DECLARE(char *) dns_get_name_type(dns_type_t type);
+DNS_DECLARE(char *) dns_get_name_class(dns_class_t type);
+
+/** protocol.c */
+DNS_DECLARE(apr_status_t) dns_query_serialize(dns_query_t *q, char *data,
+                                              int *dlen);
+DNS_DECLARE(apr_status_t) dns_query_pserialize(dns_query_t *q,
+                                               apr_pool_t *pool,
+                                               char **data, int *dlen);
+DNS_DECLARE(apr_status_t) dns_write_response(dns_message_t *dns,
+                                             char **response,
+                                             apr_size_t *len);
+DNS_DECLARE(apr_status_t) dns_read_request(dns_message_t *dns,
+                                           request_rec **r_in,
+                                           dns_query_t **q_in);
+DNS_DECLARE(dns_message_t *) dns_read_message_header(conn_rec *c);
+
+DNS_DECLARE(apr_status_t) dns_add_rr_answer(request_rec *r, dns_rr_t *rr);
+DNS_DECLARE(apr_status_t) dns_add_rr_authority(request_rec *r, dns_rr_t *rr);
+DNS_DECLARE(apr_status_t) dns_add_rr_additional(request_rec *r, dns_rr_t *rr);
+
+/** buckets.c */
+extern const apr_bucket_type_t DNS_DECLARE_DATA dns_rr_answer_bucket_type;
+extern const apr_bucket_type_t DNS_DECLARE_DATA dns_rr_authority_bucket_type;
+extern const apr_bucket_type_t DNS_DECLARE_DATA dns_rr_additional_bucket_type;
+
+#define BUCKET_IS_DNS_ANSWER(e) ((e)->type == &dns_rr_answer_bucket_type)
+#define BUCKET_IS_DNS_AUTHORITY(e) ((e)->type == &dns_rr_authority_bucket_type)
+#define BUCKET_IS_DNS_ADDITIONAL(e) ((e)->type == &dns_rr_additional_bucket_type)
+#define BUCKET_IS_DNS_RR(e) (BUCKET_IS_DNS_ANSWER(e) || \
+                             BUCKET_IS_DNS_AUTHORITY(e) || \
+                             BUCKET_IS_DNS_ADDITIONAL(e))
+
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_answer_create (
+                           const char *buf, apr_size_t length,
+                           apr_pool_t *pool, apr_bucket_alloc_t *list);
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_answer_make (
+                           apr_bucket *b, const char *buf,
+                           apr_size_t length, apr_pool_t *pool);
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_authority_create (
+                           const char *buf, apr_size_t length,
+                           apr_pool_t *pool, apr_bucket_alloc_t *list);
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_authority_make (
+                           apr_bucket *b, const char *buf,
+                           apr_size_t length, apr_pool_t *pool);
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_additional_create (
+                           const char *buf, apr_size_t length,
+                           apr_pool_t *pool, apr_bucket_alloc_t *list);
+DNS_DECLARE(apr_bucket *) dns_bucket_rr_additional_make (
+                           apr_bucket *b, const char *buf,
+                           apr_size_t length, apr_pool_t *pool);
+
+/** rr.c */
+DNS_DECLARE(void) dns_register_rr(dns_rdata_t *rdata, apr_uint16_t type);
+DNS_DECLARE(dns_rr_t *) dns_create_rr(request_rec *r, const char *name,
+                                            dns_type_t rrtype,
+                                            dns_class_t rrclass,
+                                            apr_int32_t ttl);
+DNS_DECLARE(apr_status_t) dns_rr_serialize(dns_rr_t *rr, char *data, int *dlen);
+DNS_DECLARE(apr_status_t) dns_rr_unserialize(apr_pool_t *pool,
+                                             const char *data,
+                                             dns_rr_t **rr);
+DNS_DECLARE(apr_status_t) dns_rr_pserialize(dns_rr_t *rr, apr_pool_t *pool,
+                                            char **data, int *dlen);
+
+/** mod_dns.c */
+DNS_DECLARE(int) dns_invoke_filter_init(ap_filter_t *filters);
+DNS_DECLARE(request_rec *) dns_create_request(dns_message_t *dns);
+
+/**
+ * Hook an optional hook.  Unlike static hooks, this uses a macro
+ * instead of a function.
+ */
+#define DNS_OPTIONAL_HOOK(name,fn,pre,succ,order) \
+        APR_OPTIONAL_HOOK(dns,name,fn,pre,succ,order)
+
+/**
+ * This hook is used to allow modules to implement custom processing once a
+ * DNS message header has been successfully read, but before the queries are
+ * read from the socket (and dispatched as request_rec's).  Useful for
+ * injecting input filters on the queries (without needing to ignore the
+ * message header)
+ */
+APR_DECLARE_EXTERNAL_HOOK(dns, DNS, int, post_read_request,
+                          (dns_message_t *dns))
+APR_DECLARE_EXTERNAL_HOOK(dns, DNS, int, handler,
+                          (request_rec *r))
+
+#ifdef __cplusplus
+ }
+#endif
+
+/** ensure we pull in rrs, if needed */
+#ifndef RR_H
+#include "rr.h"
+#endif
+
+#endif



Mime
View raw message