diff options
author | William A. Rowe Jr <wrowe@apache.org> | 2009-04-23 04:19:36 +0000 |
---|---|---|
committer | William A. Rowe Jr <wrowe@apache.org> | 2009-04-23 04:19:36 +0000 |
commit | 2bb8b243e0cdbafdeb9871679825caa461b3bb0d (patch) | |
tree | e5870d8238987936a338ae2336721768ca1ff85c /modules | |
parent | 08003453b3d2d07fd8cba6e93eff78ae40cc2bb6 (diff) | |
download | httpd-2bb8b243e0cdbafdeb9871679825caa461b3bb0d.tar.gz |
Introduce mod_remoteip to trunk from httpd/sandbox/mod_remoteip
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@767786 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules')
-rw-r--r-- | modules/metadata/config.m4 | 1 | ||||
-rw-r--r-- | modules/metadata/mod_remoteip.c | 488 | ||||
-rw-r--r-- | modules/metadata/mod_remoteip.dsp | 111 |
3 files changed, 600 insertions, 0 deletions
diff --git a/modules/metadata/config.m4 b/modules/metadata/config.m4 index 6eb0e4e9af..376d1b9c4d 100644 --- a/modules/metadata/config.m4 +++ b/modules/metadata/config.m4 @@ -19,5 +19,6 @@ APACHE_MODULE(usertrack, user-session tracking, , , , [ APACHE_MODULE(unique_id, per-request unique ids) APACHE_MODULE(setenvif, basing ENV vars on headers, , , yes) APACHE_MODULE(version, determining httpd version in config files, , , yes) +APACHE_MODULE(remoteip, translate header contents to an apparent client remote_ip, , , most) APACHE_MODPATH_FINISH diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c new file mode 100644 index 0000000000..dd4748bf77 --- /dev/null +++ b/modules/metadata/mod_remoteip.c @@ -0,0 +1,488 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +#include "ap_config.h" +#include "ap_mmn.h" +#include "httpd.h" +#include "http_config.h" +#include "http_connection.h" +#include "http_protocol.h" +#include "http_log.h" +#include "apr_strings.h" +#include "apr_lib.h" +#define APR_WANT_BYTEFUNC +#include "apr_want.h" +#include "apr_network_io.h" + +module AP_MODULE_DECLARE_DATA remoteip_module; + +typedef struct { + /** A proxy IP mask to match */ + apr_ipsubnet_t *ip; + /** Flagged if internal, otherwise an external trusted proxy */ + int internal; +} remoteip_proxymatch_t; + +typedef struct { + /** The header to retrieve a proxy-via ip list */ + const char *header_name; + /** A header to record the proxied IP's + * (removed as the physical connection and + * from the proxy-via ip header value list) + */ + const char *proxies_header_name; + /** A list of trusted proxies, ideally configured + * with the most commonly encountered listed first + */ + apr_array_header_t *proxymatch_ip; +} remoteip_config_t; + +typedef struct { + /** The previous proxy-via request header value */ + const char *prior_remote; + /** The unmodified original ip and address */ + const char *orig_ip; + apr_sockaddr_t *orig_addr; + /** The list of proxy ip's ignored as remote ip's */ + const char *proxy_ips; + /** The remaining list of untrusted proxied remote ip's */ + const char *proxied_remote; + /** The most recetly modified ip and address record */ + const char *proxied_ip; + apr_sockaddr_t proxied_addr; +} remoteip_conn_t; + +static void *create_remoteip_server_config(apr_pool_t *p, server_rec *s) +{ + remoteip_config_t *config = apr_pcalloc(p, sizeof *config); + /* config->header_name = NULL; + * config->proxies_header_name = NULL; + */ + return config; +} + +static void *merge_remoteip_server_config(apr_pool_t *p, void *globalv, + void *serverv) +{ + remoteip_config_t *global = (remoteip_config_t *) globalv; + remoteip_config_t *server = (remoteip_config_t *) serverv; + remoteip_config_t *config; + + config = (remoteip_config_t *) apr_palloc(p, sizeof(*config)); + config->header_name = server->header_name + ? server->header_name + : global->header_name; + config->proxies_header_name = server->proxies_header_name + ? server->proxies_header_name + : global->proxies_header_name; + config->proxymatch_ip = server->proxymatch_ip + ? server->proxymatch_ip + : global->proxymatch_ip; + return config; +} + +static const char *header_name_set(cmd_parms *cmd, void *dummy, + const char *arg) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, + &remoteip_module); + config->header_name = apr_pstrdup(cmd->pool, arg); + return NULL; +} + +static const char *proxies_header_name_set(cmd_parms *cmd, void *dummy, + const char *arg) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, + &remoteip_module); + config->proxies_header_name = apr_pstrdup(cmd->pool, arg); + return NULL; +} + +/* Would be quite nice if APR exported this */ +static int looks_like_ip(const char *ipstr) +{ + if (ap_strchr_c(ipstr, ':')) { + /* definitely not a hostname; assume it is intended to be an IPv6 address */ + return 1; + } + + /* simple IPv4 address string check */ + while ((*ipstr == '.') || apr_isdigit(*ipstr)) + ipstr++; + return (*ipstr == '\0'); +} + +static const char *proxies_set(cmd_parms *cmd, void *internal, + const char *arg) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, + &remoteip_module); + remoteip_proxymatch_t *match; + apr_status_t rv; + char *ip = apr_pstrdup(cmd->temp_pool, arg); + char *s = ap_strchr(ip, '/'); + if (s) + *s++ = '\0'; + + if (!config->proxymatch_ip) + config->proxymatch_ip = apr_array_make(cmd->pool, 1, sizeof(*match)); + match = (remoteip_proxymatch_t *) apr_array_push(config->proxymatch_ip); + match->internal = (int)internal; + + if (looks_like_ip(ip)) { + /* Note s may be null, that's fine (explicit host) */ + rv = apr_ipsubnet_create(&match->ip, ip, s, cmd->pool); + } + else + { + apr_sockaddr_t *temp_sa; + + if (s) { + return apr_pstrcat(cmd->pool, "RemoteIP: Error parsing IP ", arg, + " the subnet /", s, " is invalid for ", + cmd->cmd->name, NULL); + } + + rv = apr_sockaddr_info_get(&temp_sa, ip, APR_UNSPEC, 0, + APR_IPV4_ADDR_OK, cmd->temp_pool); + while (rv == APR_SUCCESS) + { + apr_sockaddr_ip_get(&ip, temp_sa); + rv = apr_ipsubnet_create(&match->ip, ip, NULL, cmd->pool); + if (!(temp_sa = temp_sa->next)) + break; + match = (remoteip_proxymatch_t *) + apr_array_push(config->proxymatch_ip); + match->internal = (int)internal; + } + } + + if (rv != APR_SUCCESS) { + char msgbuf[128]; + apr_strerror(rv, msgbuf, sizeof(msgbuf)); + return apr_pstrcat(cmd->pool, "RemoteIP: Error parsing IP ", arg, + " (", msgbuf, " error) for ", cmd->cmd->name, NULL); + } + + return NULL; +} + +static const char *proxylist_read(cmd_parms *cmd, void *internal, + const char *filename) +{ + char lbuf[MAX_STRING_LEN]; + char *arg; + const char *args; + const char *errmsg; + ap_configfile_t *cfp; + apr_status_t rv; + + filename = ap_server_root_relative(cmd->temp_pool, filename); + rv = ap_pcfg_openfile(&cfp, cmd->temp_pool, filename); + if (rv != APR_SUCCESS) { + return apr_psprintf(cmd->pool, "%s: Could not open file %s: %s", + cmd->cmd->name, filename, + apr_strerror(rv, lbuf, sizeof(lbuf))); + } + + while (!(ap_cfg_getline(lbuf, MAX_STRING_LEN, cfp))) { + args = lbuf; + while (*(arg = ap_getword_conf(cmd->temp_pool, &args)) != '\0') { + if (*arg == '#' || *arg == '\0') + break; + errmsg = proxies_set(cmd, internal, arg); + if (errmsg) { + errmsg = apr_psprintf(cmd->pool, "%s at line %d of %s", + errmsg, cfp->line_number, filename); + return errmsg; + } + } + } + + ap_cfg_closefile(cfp); + return NULL; +} + +static int remoteip_modify_connection(request_rec *r) +{ + conn_rec *c = r->connection; + remoteip_config_t *config = (remoteip_config_t *) + ap_get_module_config(r->server->module_config, &remoteip_module); + remoteip_conn_t *conn; +#ifdef REMOTEIP_OPTIMIZED + apr_sockaddr_t temp_sa_buff; + apr_sockaddr_t *temp_sa = &temp_sa_buff; +#else + apr_sockaddr_t *temp_sa; +#endif + apr_status_t rv; + char *remote = (char *) apr_table_get(r->headers_in, config->header_name); + char *proxy_ips = NULL; + char *parse_remote; + char *eos; + unsigned char *addrbyte; + int internal = 0; + + apr_pool_userdata_get((void*)&conn, "mod_remoteip-conn", c->pool); + + if (conn) { + if (remote && (strcmp(remote, conn->prior_remote) == 0)) { + /* TODO: Recycle r-> overrides from previous request + */ + goto ditto_request_rec; + } + else { + /* TODO: Revert connection from previous request + */ + c->remote_addr = conn->orig_addr; + c->remote_ip = (char *) conn->orig_ip; + } + } + + if (!remote) + return OK; + + remote = apr_pstrdup(r->pool, remote); + +#ifdef REMOTEIP_OPTIMIZED + memcpy(&temp_sa, c->remote_addr, sizeof(temp_sa)); + temp_sa->pool = r->pool; +#else + temp_sa = c->remote_addr; +#endif + + while (remote) { + + /* verify c->remote_addr is trusted if there is a trusted proxy list + */ + if (config->proxymatch_ip) { + int i; + remoteip_proxymatch_t *match; + match = (remoteip_proxymatch_t *)config->proxymatch_ip->elts; + for (i = 0; i < config->proxymatch_ip->nelts; ++i) { + if (apr_ipsubnet_test(match[i].ip, c->remote_addr)) { + internal = match[i].internal; + break; + } + } + if (i && i >= config->proxymatch_ip->nelts) + break; + } + + if ((parse_remote = strrchr(remote, ',')) == NULL) { + parse_remote = remote; + remote = NULL; + } + else { + *(parse_remote++) = '\0'; + } + + while (*parse_remote == ' ') + ++parse_remote; + + eos = parse_remote + strlen(parse_remote) - 1; + while (eos >= parse_remote && *eos == ' ') + *(eos--) = '\0'; + + if (eos < parse_remote) { + if (remote) + *(remote + strlen(remote)) = ','; + else + remote = parse_remote; + break; + } + +#ifdef REMOTEIP_OPTIMIZED + /* Decode remote_addr - sucks; apr_sockaddr_vars_set isn't 'public' */ + if (inet_pton(AF_INET, parse_remote, + &temp_sa_buff->sa.sin.sin_addr) > 0) { + apr_sockaddr_vars_set(temp_sa, APR_INET, temp_sa.port); + } +#if APR_HAVE_IPV6 + else if (inet_pton(AF_INET6, parse_remote, + &temp_sa->sa.sin6.sin6_addr) > 0) { + apr_sockaddr_vars_set(temp_sa, APR_INET6, temp_sa.port); + } +#endif + else { + rv = apr_get_netos_error(); +#else /* !REMOTEIP_OPTIMIZED */ + /* We map as IPv4 rather than IPv6 for equivilant host names + * or IPV4OVERIPV6 + */ + rv = apr_sockaddr_info_get(&temp_sa, parse_remote, + APR_UNSPEC, temp_sa->port, + APR_IPV4_ADDR_OK, r->pool); + if (rv != APR_SUCCESS) { +#endif + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, + "RemoteIP: Header %s value of %s cannot be parsed " + "as a client IP", + config->header_name, parse_remote); + if (remote) + *(remote + strlen(remote)) = ','; + else + remote = parse_remote; + break; + } + + addrbyte = (unsigned char *) &temp_sa->sa.sin.sin_addr; + + /* For intranet (Internal proxies) ignore all restrictions below */ + if (!internal + && ((temp_sa->family == APR_INET + /* For internet (non-Internal proxies) deny all + * RFC3330 designated local/private subnets: + * 10.0.0.0/8 169.254.0.0/16 192.168.0.0/16 + * 127.0.0.0/8 172.16.0.0/12 + */ + && (addrbyte[0] == 10 + || addrbyte[0] == 127 + || (addrbyte[0] == 169 && addrbyte[1] == 254) + || (addrbyte[0] == 172 && (addrbyte[1] & 0xf0) == 16) + || (addrbyte[0] == 192 && addrbyte[1] == 168))) +#if APR_HAVE_IPV6 + || (temp_sa->family == APR_INET6 + /* For internet (non-Internal proxies) we translated + * IPv4-over-IPv6-mapped addresses as IPv4, above. + * Accept only Global Unicast 2000::/3 defined by RFC4291 + */ + && ((temp_sa->sa.sin6.sin6_addr.s6_addr[0] & 0xe0) != 0x20)) +#endif + )) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, + "RemoteIP: Header %s value of %s appears to be " + "a private IP or nonsensical. Ignored", + config->header_name, parse_remote); + if (remote) + *(remote + strlen(remote)) = ','; + else + remote = parse_remote; + break; + } + + if (!conn) { + conn = (remoteip_conn_t *) apr_palloc(c->pool, sizeof(*conn)); + apr_pool_userdata_set(conn, "mod_remoteip-conn", NULL, c->pool); + conn->orig_addr = c->remote_addr; + conn->orig_ip = c->remote_ip; + } + + /* Set remote_ip string */ + if (!internal) { + if (proxy_ips) + proxy_ips = apr_pstrcat(r->pool, proxy_ips, ", ", + c->remote_ip, NULL); + else + proxy_ips = c->remote_ip; + } + + c->remote_addr = temp_sa; + apr_sockaddr_ip_get(&c->remote_ip, c->remote_addr); + } + + /* Nothing happened? */ + if (!conn || (c->remote_addr == conn->orig_addr)) + return OK; + + /* Fixups here, remote becomes the new Via header value, etc + * In the heavy operations above we used request scope, to limit + * conn pool memory growth on keepalives, so here we must scope + * the final results to the connection pool lifetime. + * To limit memory growth, we keep recycling the same buffer + * for the final apr_sockaddr_t in the remoteip conn rec. + */ + c->remote_ip = apr_pstrdup(c->pool, c->remote_ip); + conn->proxied_ip = c->remote_ip; + memcpy(&conn->proxied_addr, &temp_sa, sizeof(temp_sa)); + conn->proxied_addr.pool = c->pool; + c->remote_addr = &conn->proxied_addr; + + if (remote) + remote = apr_pstrdup(c->pool, remote); + conn->proxied_remote = remote; + conn->prior_remote = apr_pstrdup(c->pool, apr_table_get(r->headers_in, + config->header_name)); + if (proxy_ips) + proxy_ips = apr_pstrdup(c->pool, proxy_ips); + conn->proxy_ips = proxy_ips; + + /* Unset remote_host string DNS lookups */ + c->remote_host = NULL; + c->remote_logname = NULL; + +ditto_request_rec: + if (conn->proxied_remote) + apr_table_setn(r->headers_in, config->header_name, + conn->proxied_remote); + else + apr_table_unset(r->headers_in, config->header_name); + if (conn->proxy_ips) { + apr_table_setn(r->notes, "remoteip-proxy-ip-list", conn->proxy_ips); + if (config->proxies_header_name) + apr_table_setn(r->headers_in, config->proxies_header_name, + conn->proxy_ips); + } + + ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, + conn->proxy_ips + ? "Using %s as client's IP by proxies %s" + : "Using %s as client's IP by internal proxies", + conn->proxied_ip, conn->proxy_ips); + return OK; +} + +static const command_rec remoteip_cmds[] = +{ + AP_INIT_TAKE1("RemoteIPHeader", header_name_set, NULL, RSRC_CONF, + "Specifies a request header to trust as the client IP, " + "e.g. X-Forwarded-For"), + AP_INIT_TAKE1("RemoteIPProxiesHeader", proxies_header_name_set, + NULL, RSRC_CONF, + "Specifies a request header to record proxy IP's, " + "e.g. X-Forwarded-By; if not given then do not record"), + AP_INIT_ITERATE("RemoteIPTrustedProxy", proxies_set, 0, RSRC_CONF, + "Specifies one or more proxies which are trusted " + "to present IP headers"), + AP_INIT_ITERATE("RemoteIPInternalProxy", proxies_set, (void*)1, RSRC_CONF, + "Specifies one or more internal (transparent) proxies " + "which are trusted to present IP headers"), + AP_INIT_TAKE1("RemoteIPTrustedProxyList", proxylist_read, 0, + RSRC_CONF | EXEC_ON_READ, + "The filename to read the list of trusted proxies, " + "see the RemoteIPTrustedProxy directive"), + AP_INIT_TAKE1("RemoteIPInternalProxyList", proxylist_read, (void*)1, + RSRC_CONF | EXEC_ON_READ, + "The filename to read the list of internal proxies, " + "see the RemoteIPInternalProxy directive"), + { NULL } +}; + +static void register_hooks(apr_pool_t *p) +{ + ap_hook_post_read_request(remoteip_modify_connection, NULL, NULL, APR_HOOK_FIRST); +} + +module AP_MODULE_DECLARE_DATA remoteip_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + create_remoteip_server_config, /* create per-server config structure */ + merge_remoteip_server_config, /* merge per-server config structures */ + remoteip_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/metadata/mod_remoteip.dsp b/modules/metadata/mod_remoteip.dsp new file mode 100644 index 0000000000..c59245d778 --- /dev/null +++ b/modules/metadata/mod_remoteip.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_remoteip" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_remoteip - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_remoteip.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_remoteip.mak" CFG="mod_remoteip - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_remoteip - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_remoteip - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_remoteip - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_remoteip_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_remoteip.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_remoteip.so" /d LONG_NAME="remoteip_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_remoteip.so" /base:@..\..\os\win32\BaseAddr.ref,mod_remoteip.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_remoteip.so" /base:@..\..\os\win32\BaseAddr.ref,mod_remoteip.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_remoteip.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_remoteip - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_remoteip_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_remoteip.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_remoteip.so" /d LONG_NAME="remoteip_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_remoteip.so" /base:@..\..\os\win32\BaseAddr.ref,mod_remoteip.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_remoteip.so" /base:@..\..\os\win32\BaseAddr.ref,mod_remoteip.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_remoteip.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_remoteip - Win32 Release" +# Name "mod_remoteip - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_remoteip.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project |