mod_extract_forwarded を改造

mod_proxy_http を使うかどうかでソースを書き換えなくちゃいけないのは面倒なので,APR の DSO 関数とか使ってがんばってみました。

本来は関数の hook は register_hooks callback stage で登録するのが筋なんですが,ap_pre_config hook で登録するという黒魔術を使ってます。これが ap_post_config だとなぜか proxy_hook_scheme_handler hook がうまく呼んでもらえないという罠((そんかわし,ap_pre_config だとなぜか Apache 内的再起動のあおりを食わないというメリットもありました))。まさに黒魔術。

mod_proxy 等が DSO ではなく static link されてるとうまくいきません。まぁそこはそれ。あと win32 だと apr_dso_sym で取得する関数のプロトタイプ typedef が微妙なことになってしまうかも。

#ちなみに以前のパッチは作者には投げてあるんですが,レスポンスがありません


以下退屈なパッチが続きます。いつの日かどこぞに check-in するので,参考程度扱いで。

--- mod_extract_forwarded.c     (revision 2)
+++ mod_extract_forwarded.c     (revision 8)
@@ -117,16 +117,6 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-/* 
- * #define USING_proxy_http_module if proxy_http.c module is either 
- * compiled into Apache 2 or it is being loaded as a DSO. If proxy_http.c 
- * module is not loaded then this module will generate an error when and
- * if it is loaded as a DSO. In that case comment out the #define, recompile
- * and reinstall this module. BUT do not forget to change things back if
- * proxy_http.c module is reinstated
- */
-#define USING_proxy_http_module 1 
-
 /*--------------------------------------------------------------------------*/
 /*                                                                          */
 /* Data declarations.                                                       */
@@ -758,7 +748,7 @@
     {
         if (conf->debug == MEF_DEBUG_ON) 
         {
-            fprintf(stderr,"MEF: phase:%s, $s not acceptabler proxy, %s\n", 
+            fprintf(stderr,"MEF: phase:%s, %s not acceptabler proxy, %s\n", 
                     phase, conn->remote_ip, r->unparsed_uri);
             fflush(stderr);
         }
@@ -925,6 +915,9 @@
  * spoof one) is added to the X-Forwarded-For header.
  */
 static int mef_before_proxy_http(request_rec *r, 
+#if AP_SERVER_MINORVERSION_NUMBER >= 2
+                                 proxy_worker *worker,
+#endif
                                  proxy_server_conf *pconf,
                                  char *url, const char *proxyname, 
                                  apr_port_t proxyport)
@@ -977,6 +970,97 @@
     return DECLINED;
 }
 
+static const char ID_MOD_ME[]         = "mod_extract_forwarded";
+static const char ID_MOD_PROXY[]      = "mod_proxy.c";
+static const char ID_MOD_PROXY_HTTP[] = "mod_proxy_http.c";
+
+typedef PROXY_DECLARE(void) proxy_hook_scheme_handler_t
+    (proxy_HOOK_scheme_handler_t *pf,
+     const char * const *aszPre, const char * const *aszSucc, int nOrder);
+
+static module *mod_proxy_is_installed(apr_pool_t *p)
+{
+    module *mod_proxy;
+
+    mod_proxy = ap_find_linked_module(ID_MOD_PROXY);
+    if (! mod_proxy) {
+        ap_log_perror(APLOG_MARK, APLOG_INFO, 0, p,
+                      "%s: mod_proxy is not loaded", ID_MOD_ME);
+        return NULL;
+    }
+    if (! ap_find_linked_module(ID_MOD_PROXY_HTTP)) {
+        ap_log_perror(APLOG_MARK, APLOG_INFO, 0, p,
+                      "%s: mod_proxy_http is not loaded", ID_MOD_ME);
+        return NULL;
+    }
+
+    return mod_proxy;
+}
+
+static int install_proxy_hook_scheme_handler(module *mod_proxy, apr_pool_t *p)
+{
+    static const char *const aszSucc[] = { ID_MOD_PROXY_HTTP, NULL };
+    apr_status_t r;
+    apr_dso_handle_t *dso;
+    apr_dso_handle_sym_t handle_sym;
+    proxy_hook_scheme_handler_t *hook_scheme_handler;
+
+    dso = (apr_dso_handle_t *) mod_proxy->dynamic_load_handle;
+
+    if (! dso) {
+        ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p,
+                      "%s: mod_proxy seems not to be DSO module", ID_MOD_ME);
+        return !OK;
+    }
+
+    r = apr_dso_sym(&handle_sym, dso, "proxy_hook_scheme_handler");
+    if (r != APR_SUCCESS) {
+        char my_error[256];
+
+        ap_log_perror(APLOG_MARK, APLOG_ERR, r, p,
+                      "%s: couldn't get proxy_hook_scheme_handler (%s)",
+                      ID_MOD_ME,
+                      apr_dso_error(dso, my_error, sizeof(my_error)));
+        return !OK;
+    }
+    /* avoid warning for strict-aliasing */
+    hook_scheme_handler = (proxy_hook_scheme_handler_t *) handle_sym;
+
+    hook_scheme_handler(mef_before_proxy_http, NULL, aszSucc,
+                        APR_HOOK_FIRST);
+
+    ap_log_perror(APLOG_MARK, APLOG_INFO, 0, p,
+                  "%s: hook installed", ID_MOD_ME);
+
+    return OK;
+}
+
+/*
+ * NOTICE:
+ *   ap_hook_post_config() is too late.
+ *   ap_hook_pre_config() seems to be called only once
+ *       whereas ap_hook_post_config() is called twice.
+ */
+static int mef_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
+{
+    int r;
+    module *mod_proxy = mod_proxy_is_installed(p);
+    if (! mod_proxy)
+        return OK;
+
+    /* 
+     * Only need to register the following handlers if proxy_http_module
+     * is going to be loaded
+     */
+    r = install_proxy_hook_scheme_handler(mod_proxy, p);
+    if (r != OK)
+        return r;
+
+    ap_hook_log_transaction(mef_logging, NULL, NULL, APR_HOOK_FIRST);
+
+    return OK;
+}
+
 /*--------------------------------------------------------------------------*/
 /*                                                                          */
 /* Data structures pulling all the mef module's bits together               */
@@ -987,6 +1071,8 @@
  */
 static void mef_register_hooks(apr_pool_t *p)
 {
+    ap_hook_pre_config(mef_pre_config, NULL, NULL, APR_HOOK_LAST);
+
     ap_hook_post_read_request(mef_post_read_request, NULL, NULL, 
                               APR_HOOK_FIRST);
     ap_hook_translate_name(mef_uri_translate, NULL, NULL, APR_HOOK_FIRST);
@@ -996,16 +1082,6 @@
  *    ap_hook_header_parser(mef_header_parser, NULL, NULL, APR_HOOK_FIRST);
  */
     ap_hook_access_checker(mef_access_check, NULL, NULL, APR_HOOK_FIRST);   
-#ifdef USING_proxy_http_module
-    /* 
-     * Only need to register the following handlers if proxy_http_module
-     * is going to be loaded
-     */
-    static const char *const mef_proxy_b4[] = { "proxy_http.c", NULL };
-    proxy_hook_scheme_handler(mef_before_proxy_http, NULL, mef_proxy_b4,
-                              APR_HOOK_FIRST);
-    ap_hook_log_transaction(mef_logging, NULL, NULL, APR_HOOK_FIRST);
-#endif /* USING_proxy_http_module */
 }
 
 /*