pax_global_header 0000666 0000000 0000000 00000000064 12476363444 0014527 g ustar 00root root 0000000 0000000 52 comment=c2f7fbc7d4fca963f7301bd16497947e3b8bbb4b
geoip-api-mod_geoip2-1.2.10/ 0000775 0000000 0000000 00000000000 12476363444 0015504 5 ustar 00root root 0000000 0000000 geoip-api-mod_geoip2-1.2.10/.uncrustify.cfg 0000664 0000000 0000000 00000006410 12476363444 0020457 0 ustar 00root root 0000000 0000000 #
# based on uncrustify config file for the linux kernel
#
code_width = 80
indent_case_brace = 4
indent_columns = 4
indent_label = 2 # pos: absolute col, neg: relative column
indent_with_tabs = 0
#
# inter-symbol newlines
#
nl_brace_else = remove # "} else" vs "} \n else" - cuddle else
nl_brace_while = remove # "} while" vs "} \n while" - cuddle while
nl_do_brace = remove # "do {" vs "do \n {"
nl_else_brace = remove # "else {" vs "else \n {"
nl_enum_brace = remove # "enum {" vs "enum \n {"
nl_fcall_brace = remove # "list_for_each() {" vs "list_for_each()\n{"
nl_fdef_brace = force # "int foo() {" vs "int foo()\n{"
nl_for_brace = remove # "for () {" vs "for () \n {"
nl_func_var_def_blk = 0 # don't add newlines after a block of var declarations
nl_if_brace = remove # "if () {" vs "if () \n {"
nl_multi_line_define = true
nl_struct_brace = remove # "struct {" vs "struct \n {"
nl_switch_brace = remove # "switch () {" vs "switch () \n {"
nl_union_brace = remove # "union {" vs "union \n {"
nl_while_brace = remove # "while () {" vs "while () \n {"
#
# Source code modifications
#
mod_full_brace_do = force # "do a--; while ();" vs "do { a--; } while ();"
mod_full_brace_for = force # "for () a--;" vs "for () { a--; }"
mod_full_brace_if = force # "if (a) a--;" vs "if (a) { a--; }"
mod_full_brace_nl = 3 # don't remove if more than 3 newlines
mod_full_brace_while = force # "while (a) a--;" vs "while (a) { a--; }"
mod_paren_on_return = remove # "return 1;" vs "return (1);"
#
# inter-character spacing options
#
sp_after_cast = remove # "(int) a" vs "(int)a"
sp_after_comma = force
sp_after_sparen = force # "if () {" vs "if (){"
sp_arith = force
sp_assign = force
sp_assign = force
sp_before_comma = remove
sp_before_ptr_star = force # "char *foo" vs "char* foo
sp_before_sparen = force # "if (" vs "if("
sp_between_ptr_star = remove # "char * *foo" vs "char **foo"
sp_bool = force
sp_compare = force
sp_func_call_paren = remove # "foo (" vs "foo("
sp_func_def_paren = remove # "int foo (){" vs "int foo(){"
sp_func_proto_paren = remove # "int foo ();" vs "int foo();"
sp_inside_braces = force # "{ 1 }" vs "{1}"
sp_inside_braces_enum = force # "{ 1 }" vs "{1}"
sp_inside_braces_struct = force # "{ 1 }" vs "{1}"
sp_inside_sparen = remove
sp_paren_brace = force
sp_sizeof_paren = remove # "sizeof (int)" vs "sizeof(int)"
#
# Aligning stuff
#
align_enum_equ_span = 4 # '=' in enum definition
align_nl_cont = true
align_on_tabstop = FALSE # align on tabstops
align_right_cmt_span = 3
align_struct_init_span = 1
align_struct_init_span = 3 # align stuff in a structure init '= { }'
align_var_def_star_style = 2 # void *foo;
align_var_struct_span = 0
align_with_tabs = FALSE # use tabs to align
geoip-api-mod_geoip2-1.2.10/Changes 0000664 0000000 0000000 00000012041 12476363444 0016775 0 ustar 00root root 0000000 0000000 1.2.10 2015-03-06
- Update docs to note that GeoIP configuration directives cannot be placed
in .htaccess files.
- Fix small memleak (Boris Zentner)
- A segfault when using multi-threaded workers was fixed. (Fix from thinker0.
GitHub #16.)
- Several instances of manual memory management were switched to use the
use Apache's memory pool. (Fix from thinker0. GitHub #16.)
1.2.9 2014-03-20
- Added a new directive, GeoIPScanProxyHeaderField, to specify a custom
header which contains the client's IP address (Sascha Kuehndel)
- Added the ability to forward the result fields to a backend server/proxy
via request header (Sascha Kuehndel)
1.2.9 2013-01-08
- Add GeoIPUseFirstNonPrivateXForwardedForIP option (Boris Zentner)
- Support Apache 2.4 (Boris Zentner)
- Use GeoIP_id_by_addr_v6 instead of GeoIP_country_id_by_addr_v6 (Boris Zentner)
- Include util_script.h to silence warning about ap_add_common_vars (Boris Zentner)
1.2.7 2011-08-23
- Add support for GEOIP_NETSPEED_REV1 (Boris Zentner)
- Experimental support for GEOIP_COUNTRY_EDITION_V6 (Boris Zentner)
- Add GEOIP_DOMAIN_EDITION support (Boris Zentner)
1.2.6 2008-09-11
- GEOIP_METRO_CODE replace the depreciated GEOIP_DMA_CODE (Boris Zentner)
1.2.5 2008-08-13
! Fix GEOIP_REGION and GEOIP_COUNTRY_CODE when used with the GeoIPRegion
database. Both are only set if a region or country was found. Previously
a empty string was assigned to both (Boris Zentner)
- Add GEOIP_REGION_NAME for City and Region databases (Boris Zentner)
1.2.4 2008-06-10
! mod_geoip2 has sets GEOIP_COUNTRY_CODE to -- for unknown countries when
used with the country database. But for any other database (City for
example) GEOIP_COUNTRY_CODE is unset for unknown countries. This is
fixed now. Same for GEOIP_CONTINENT_CODE and GEOIP_COUNTRY_NAME. (Boris
Zentner)
- Add GEOIP_ADDR. That's the address used to compute the geoip
information. Exported as env, notes or both as usual (Jason Caldwell)
- Try to run always before mod_setenvif and mod_rewrite. (Boris Zentner)
1.2.3 2008-04-26
- Skip files that we can not open for some reason (permission/typo). Check
and skip empty slots in geoip_header_parser (Boris Zentner)
- Slight performance increase - don't make per_dir ap_get_module_config
call where we return DECLINED because cfg->GeoIPEnabled is true (Guenter
Knauf)
- NetWare/Win32 compilation fixes, since can't declare vars in middle of
code (Guenter Knauf)
1.2.2 2008-03-18
- Fix race condition for IO based caches like Standard. MMapCache and
MemoryCache are not affected. (Boris Zentner)
1.2.1 2007-12-17
! Notice - all directives are _only_ valid in server context except
GeoIPEnabled. Check you configuration with apachectl configtest (Boris
Zentner)
- Added MMapCache option (Boris Zentner)
- Change GeoIPEnabled from a serverwide option to a
server/directory/location keyword. (Boris Zentner)
- Fix a small memleak per child. Allocated in geoip_child_init free in
geoip_cleanup (Boris Zentner)
- GeoIP databases get used serverwide now. Not per child. See the
README. (Boris Zentner)
- Update README with more examples (Boris Zentner)
- Added support for UTF8 output for GeoIP City databases (Boris Zentner)
1.2.0 2007-08-30
- Fix segfault issue if GeoIP.dat file cannot be opened (Vladimir
Sedlacek)
- Added support for GEOIP_CONTINENT_CODE for GeoIP Country and City (Frank
Mather)
- Added GeoIPScanProxyHeaders directive to handle X-Forwarded-For headers
(Frank Mather)
- Updated documentation to specify that GeoIPFlags need to be passed
as second parameter to GeoIPDBFile, instead of using the GeoIPFlags directive
1.1.8 2006-04-28
- Updated README file with GeoIPFlags docs and performance tips
- Added apr_strings.h include (Dann Frazier, Fixes Debian #357387)
- Added support for IndexCache
1.1.7 2005-08-01
- Copied docs in mod_geoip1.3 in README on how to redirect and block by country
- Fixed Garbage characters appearing in GeoIP Postal Code field, this
bug was introduced in 1.1.3
1.1.6 2005-05-17
- Fixed empty fields for GeoIP Region fields, this bug
was introduced in 1.1.3
1.1.5 2005-04-19
- Removed dependence on DNS resolver for GeoIP Region and Netspeed databases
1.1.4 2004-12-23
- Fixed Garbage characters appearing in GeoIP City/Region field, this
bug was introduced in 1.1.3
1.1.3 2004-12-09
- Added support for GeoIPOutput
- Changed command setup to AP_INIT_TAKE12 from AP_INIT_TAKE1 GeoIPDBFile (merv)
- Memory Leak fix when using GeoIP Region database
- Memory Leak fix when using GeoIP City database (Shane Nelson)
1.1.2 2004-08-12
- Added support for GeoIP Netspeed Edition (Frank Mather)
- Added support for GeoIP City setting GEOIP_DMA_CODE, GEOIP_AREA_CODE, GEOIP_LATITUDE,
GEOIP_LONGITUDE, and GEOIP_POSTAL_CODE (Frank Mather)
1.1.1 2004-07-12
- Added more documentation for using from PHP
- Fixed compile errors and warnings
1.1.0 2004-04-19
- Added support for GeoIP Region, City, ISP and Organization (Frank Mather)
1.0.6 2002-08-30
- Added GeoIP_delete upon cleanup (Corris Randall)
1.0.5 2002-08-29
- Initial Release (Corris Randall)
geoip-api-mod_geoip2-1.2.10/INSTALL.md 0000664 0000000 0000000 00000003370 12476363444 0017137 0 ustar 00root root 0000000 0000000 # Installation
## Requirements
Apache 2.0.40 or higher installed If using RPM, the httpd-devel package
containing apxs may need to be installed [GeoIP 1.4.8 or higher
installed](https://github.com/maxmind/geoip-api-c/releases).
## Building
To build mod_geoip as a dynamically loadable module:
```
apxs -i -a -L/usr/local/lib -I/usr/local/include -lGeoIP -c mod_geoip.c
```
`-I/usr/local/include` is where the GeoIP.h header file is installed.
`-L/usr/local/lib` is where the libGeoIP library is located.
This will put the correct LoadModule statement.
## Configuration
To enable the module, place
```
GeoIPEnable On
```
inside your httpd.conf file. The `` block is not required but is
recommended.
You can optionally specify the data file by using:
```
GeoIPEnable On
GeoIPDBFile /usr/tmp/GeoIP.dat
```
See the README.md file for more details on the configuration
## Troubleshooting
On RedHat 9, apxs places
```
LoadModule geoip_module /usr/lib/httpd/modules/mod_geoip.so
```
Inside a
```
```
Block.
If mod_geoip2 doesn't work, try taking the LoadModule geoip_module line outside
the `` block.
If you get the following errors:
```
parse error before "geoip_module"
warning: data definition has no type or storage class
```
Or
```
syntax error before "geoip_module"
```
Make sure that the apxs script belongs to the Apache server you are using.
These error messages result from using a Apache 1.3 apxs script with a Apache
2.x server.
If you get a `libGeoIP.so.1: cannot open shared object file: No such file or
directory` error, add `/usr/local/lib` to `/etc/ld.so.conf` then run
`/sbin/ldconfig /etc/ld.so.conf`
geoip-api-mod_geoip2-1.2.10/LICENSE 0000664 0000000 0000000 00000004520 12476363444 0016512 0 ustar 00root root 0000000 0000000 /* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2004 MaxMind, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*/
geoip-api-mod_geoip2-1.2.10/README.md 0000664 0000000 0000000 00000043104 12476363444 0016765 0 ustar 00root root 0000000 0000000 GeoIP Legacy Apache Module
==========================
Important Note
--------------
This API is for the GeoIP Legacy format (dat). To read the MaxMind DB format
(mmdb) used by GeoIP2, please see
[mod_maxminddb](https://github.com/maxmind/mod_maxminddb)
Description
-----------
The mod_geoip2 module embeds GeoIP Legacy database lookups into the
Apache web server. It is only capable of looking up the IP of a client
that connects to the web server, as opposed to looking up arbitrary
addresses.
This module works with Apache 2. Please use
[mod_geoip](http://www.maxmind.com/download/geoip/api/mod_geoip/mod_geoip-latest.tar.gz)
with Apache 1.
Installation
------------
You can [download
mod_geoip2](https://github.com/maxmind/geoip-api-mod_geoip2/releases)
from GitHub or get the latest development version from
[GitHub](https://github.com/maxmind/geoip-api-mod_geoip2). See the
`INSTALL` file in the tarball for installation details.
Overview
--------
The mod_geoip2 module uses the libGeoIP library to look up geolocation
information for a client as part of the http request process. This
module is free software, and is licensed under the [Apache
license](http://www.apache.org/licenses/LICENSE-2.0.html).
To compile and install this module, you must first install [libGeoIP
1.4.3](/?page_id=44#MaxMind-Supported_APIs) or newer.
The mod_geoip2 module takes effect either during request header parsing
phase or the post read request phase, depending on whether it is
configured for server-wide use or for a specific location/directory.
When enabled, the module looks at the incoming IP address and sets some
variables which provide geolocation information for that IP. The
variables it set depend on the specific GeoIP Legacy database being used
(Country, City, ISP, etc.). These variables can be set in either the
request notes table, the environment or both depending on the server
configuration.
Configuration
-------------
With the exception of `GeoIPEnable`, all GeoIP configuration
directives must be placed in the server-wide context of the main server
config. (Please see [Server vs Directory
context](#Server_vs_Directory_context) for a full explanation). After
installing the module, make sure that
GeoIPEnable On
is set in your Apache configuration file or an `.htaccess` file. This
will call the GeoIP Legacy Country database from its default location
(e.g. /usr/local/share/GeoIP/GeoIP.dat)
If you want to specify options, for example to use a different database
or to pass caching options, you can use the `GeoIPDBFile` directive:
### File and Caching Directives
GeoIPDBFile /path/to/GeoIP.dat [GeoIPFlag]
For example:
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
GeoIPDBFile /usr/local/share/GeoIP/GeoIPOrg.dat Standard
The default GeoIPFlag value is Standard, which does not perform any
caching, but uses the least memory. To turn on memory caching use:
GeoIPDBFile /path/to/GeoIP.dat MemoryCache
The memory cache option can use a large amount of memory. We recommend
that you use Memory Caching only for the smaller database files, such as
GeoIP Legacy Country and GeoIP Legacy ISP.
Another MemoryCache option is MMapCache, which uses the the `mmap`
system call to map the database file into memory.
If you would like the API to check to see if your local GeoIP Legacy
files have been updated, set the `CheckCache` flag:
GeoIPDBFile /path/to/GeoIP.dat CheckCache
Before making a call to the database, geoip will check the GeoIP.dat
file to see if it has changed. If it has, then it will reload the file.
With this option, you do not have to restart Apache when you update your
GeoIP Legacy databases.
If you would like to turn on partial memory caching, use the
`IndexCache` flag:
GeoIPDBFile /path/to/GeoIP.dat IndexCache
The IndexCache option caches the most frequently accessed index portion
of the database, resulting in faster lookups than StandardCache, but
less memory usage than MemoryCache. This is especially useful for larger
databases such as GeoIP Legacy Organization and GeoIP Legacy City. For
the GeoIP Legacy Country, Region and Netspeed databases, setting the
IndexCache option just causes the C API to use the MemoryCache.
Currently, multiple GeoIPFlags options can not be combined.
### Enabling UTF-8 Output
You may change the output charset from ISO-8859-1 (Latin-1) to UTF-8
with this directive:
GeoIPEnableUTF8 On
By default mod_geoip2 sets variables in both the notes table and
environment. For performance reasons you may want to set only the one
you use. To do so, use the `GeoIPOutput` configuration directive:
### Output Variable Location
GeoIPOutput Notes # Sets the Apache notes table only
GeoIPOutput Env # Sets environment variables only
GeoIPOutput Request # Sets input headers with the geo location information
GeoIPOutput All # Sets all three (default behaviour)
### Proxy-Related Directives
By default, this module will simply look at the IP address of the
client. However, if the client is using a proxy, this will be the
address of the proxy. You can use the `GeoIPScanProxyHeaders` directive
to look at proxy-related headers.
GeoIPScanProxyHeaders On
When this is set, the module will look at several other sources for the
IP address, in this order:
- The `HTTP_CLIENT_IP` environment variable (set by Apache).
- The `HTTP_X_FORWARDED_FOR` environment variable (set by Apache).
- The `X-Forwarded-For` for header (set by a proxy).
- The `HTTP_REMOTE_ADDR` environment variable (set by Apache).
This module will use the first IP address it finds in one of these
locations *instead* of the IP address the client connected from.
Some of these variables may contain a comma-separate list of IP
addresses (when a client goes through multiple proxies). In this case,
the default behavior is to use the first IP address. You can set the
`GeoIPUseLastXForwardedForIP` directive to use the last address instead:
GeoIPUseLastXForwardedForIP On
Or use `GeoIPUseFirstNonPrivateXForwardedForIP` to use the first non
private IP Address.
GeoIPUseFirstNonPrivateXForwardedForIP On
Apache 2.4 users using mod_remoteip to pick the IP address of the user
should disable GeoIPScanProxyHeaders. Mod_geoip2 will use whatever
mod_remoteip provides.
GeoIPScanProxyHeaderField FieldName
Sometimes it is useful to use another field as the source for the
client's IP address. You can set this directive to tell this module
which header to look at in order to determine the client's IP address.
Output Variables
----------------
As noted above, these variables can be set in either the Apache request
notes table, the environment, or both. The specific variables which are
set depend on the database you are using.
### GeoIP Country Edition Output Variables
#### GEOIP_ADDR
The address used to calculate the GeoIP output.
#### GEOIP_CONTINENT_CODE
A two-character code for the continent associated with the IP address.
The possible codes are:
- **AF** - Africa
- **AS** - Asia
- **EU** - Europe
- **NA** - North America
- **OC** - Oceania
- **SA** - South America
#### GEOIP_COUNTRY_CODE
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](/?p=384).
- **A2** - a [satellite provider](/?p=385).
- **EU** - an IP in a block used by multiple [European](/?p=386)
countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](/?p=386) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
#### GEOIP_COUNTRY_NAME
The country name associated with the IP address.
### GeoIP Region Edition Output Variables
#### GEOIP_ADDR
The address used to calculate the GeoIP output.
#### GEOIP_COUNTRY_CODE
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](/?page_id=23#anonproxy).
- **A2** - a [satellite provider](/?page_id=23#satellite).
- **EU** - an IP in a block used by multiple
[European](/?page_id=23#euapcodes) countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](/?page_id=23#euapcodes) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
#### GEOIP_REGION_NAME
The region name associated with the IP address.
#### GEOIP_REGION
A two character [ISO-3166-2](http://en.wikipedia.org/wiki/ISO_3166-2) or
[FIPS 10-4](http://en.wikipedia.org/wiki/FIPS_10-4) code for the
state/region associated with the IP address.
For the US and Canada, we return an ISO-3166-2 code. In addition to the
standard ISO codes, we may also return one of the following:
- **AA** - Armed Forces America
- **AE** - Armed Forces Europe
- **AP** - Armed Forces Pacific
We return a FIPS code for all other countries.
We provide a [CSV file which maps our region codes to region
names](http://www.maxmind.com/download/geoip/misc/region_codes.csv). The
columns are ISO country code, region code (FIPS or ISO), and the region
name.
### GeoIP City Edition Output Variables
#### GEOIP_ADDR
The address used to calculate the GeoIP output.
#### GEOIP_CONTINENT_CODE
A two-character code for the continent associated with the IP address.
The possible codes are:
- **AF** - Africa
- **AS** - Asia
- **EU** - Europe
- **NA** - North America
- **OC** - Oceania
- **SA** - South America
#### GEOIP_COUNTRY_CODE
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](/?page_id=23#anonproxy).
- **A2** - a [satellite provider](/?page_id=23#satellite).
- **EU** - an IP in a block used by multiple
[European](/?page_id=23#euapcodes) countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](/?page_id=23#euapcodes) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
#### GEOIP_REGION
A two character [ISO-3166-2](http://en.wikipedia.org/wiki/ISO_3166-2) or
[FIPS 10-4](http://en.wikipedia.org/wiki/FIPS_10-4) code for the
state/region associated with the IP address.
For the US and Canada, we return an ISO-3166-2 code. In addition to the
standard ISO codes, we may also return one of the following:
- **AA** - Armed Forces America
- **AE** - Armed Forces Europe
- **AP** - Armed Forces Pacific
We return a FIPS code for all other countries.
We provide a [CSV file which maps our region codes to region
names](http://www.maxmind.com/download/geoip/misc/region_codes.csv). The
columns are ISO country code, region code (FIPS or ISO), and the region
name.
#### GEOIP_REGION_NAME
The region name associated with the IP address.
#### GEOIP_CITY
The city or town name associated with the IP address. See our [list of
cities](http://www.maxmind.com/GeoIPCity-534-Location.csv) to see all
the possible return values. This list is updated on a regular basis.
#### GEOIP_METRO_CODE
The metro code associated with the IP address. These are only available
for IP addresses in the US. MaxMind returns the [same metro codes as the
Google AdWords
API](https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions).
#### GEOIP_AREA_CODE
The telephone area code associated with the IP address. These are only
available for IP addresses in the US.
#### GEOIP_LATITUDE
The latitude associated with the IP address.
#### GEOIP_LONGITUDE
The longitude associated with the IP address.
#### GEOIP_POSTAL_CODE
The postal code associated with the IP address. These are available for
some IP addresses in the US, Canada, Germany, and United Kingdom.
### GeoIP ISP Edition Output Variables
#### GEOIP_ADDR
The address used to calculate the GeoIP output.
#### GEOIP_ISP
The name of the ISP associated with the IP address.
### GeoIP Organization Edition Output Variables
#### GEOIP_ADDR
The address used to calculate the GeoIP output.
#### GEOIP_ORGANIZATION
The name of the organization associated with the IP address.
### GeoIP Netspeed Edition Output Variables
#### GEOIP_ADDR
The address used to calculate the GeoIP output.
#### GEOIP_NETSPEED
The network speed associated with the IP address. This can be one of the
following values:
- **Dialup**
- **Cable/DSL**
- **Corporate**
- **Cellular**
### GeoIPv6 Edition (experimental) Output Variables
#### GEOIP_ADDR
The address used to calculate the GeoIP output.
#### GEOIP_CONTINENT_CODE_V6
A two-character code for the continent associated with the IP address.
The possible codes are:
- **AF** - Africa
- **AS** - Asia
- **EU** - Europe
- **NA** - North America
- **OC** - Oceania
- **SA** - South America
#### GEOIP_COUNTRY_CODE_V6
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](/?page_id=23#anonproxy).
- **A2** - a [satellite provider](/?page_id=23#satellite).
- **EU** - an IP in a block used by multiple
[European](/?page_id=23#euapcodes) countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](/?page_id=23#euapcodes) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
#### GEOIP_COUNTRY_NAME_V6
The country name associated with the IP address.
Examples
--------
Here are some examples of how you can use mod_geoip2.
### Redirecting a client based on country
This example show you how to redirect a client based on the country code
that GeoIP sets.
GeoIPEnable On
GeoIPDBFile /path/to/GeoIP.dat
# Redirect one country
RewriteEngine on
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^CA$
RewriteRule ^(.*)$ http://www.canada.com$1 [R,L]
# Redirect multiple countries to a single page
RewriteEngine on
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^(CA|US|MX)$
RewriteRule ^(.*)$ http://www.northamerica.com$1 [R,L]
### Blocking a client based on country
This example show you how to block clients based on the country code
that GeoIP sets.
GeoIPEnable On
GeoIPDBFile /path/to/GeoIP.dat
SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
# ... place more countries here
Deny from env=BlockCountry
### Allowing clients based on country
This example show you how to allow only clients from specific countries.
GeoIPEnable On
GeoIPDBFile /path/to/GeoIP.dat
SetEnvIf GEOIP_COUNTRY_CODE US AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE CA AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE MX AllowCountry
# ... place more countries here
Deny from all
Allow from env=AllowCountry
### Server vs Directory context
All directives except GeoIPEnable are server config only, i.e., you type
it only once per server config. Otherwise the latest wins.
``` {.lang:default .decode:true}
GeoIPEnable Off
GeoIPEnableUTF8 On
GeoIPOutput Env
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
GeoIPDBFile /usr/local/share/GeoIP/GeoIPCity.dat MemoryCache
GeoIPDBFile /usr/local/share/GeoIP/GeoIPOrg.dat MemoryCache
```
GeoIPEnable is useful in server or directory context. For example:
GeoIP is only available for a specific location:
``` {.lang:default .decode:true}
GeoIPEnable Off
GeoIPEnableUTF8 On
GeoIPOutput Env
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
# GeoIP information is avail only inside /xxx
GeoIPEnable On
...
...
```
GeoIP is available for all locations:
``` {.lang:default .decode:true}
GeoIPEnable On
GeoIPEnableUTF8 On
GeoIPOutput Env
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
# This doesn't work, because it's already been enabled in the server-wide
# config!
GeoIPEnable On
GeoIPEnable Off
```
Memory Usage
------------
Starting with mod_geoip2 version 1.2.1, all Apache child processes
share the same database when you set the MemoryCache or MMapCache flag.
Memory usage is about the same as the database file size, no matter how
many child processes Apache spawns. The only thing to remember is ask
Apache to update if your database changes. Use the graceful restart
option to do so without stopping Apache.
Performance
-----------
For improved performance, you may want to enable mod_geoip only for
specific HTML pages. If you want to use the mod_geoip module site-wide,
you may still be able to only use it for HTML pages and not images. To
restrict the pages where mod_geoip2 is used, place the `GeoIPEnable On`
directive inside a , or directive, see:
[httpd.apache.org/docs/2.0/sections.html](http://httpd.apache.org/docs/2.0/sections.html)
Troubleshooting
---------------
If the module is not working, make sure that the httpd user (e.g.
nobody) has read access to the GeoIP database file(s) you are using.
If the GeoIP variables do not show up please make sure that the client
IP address is not on a private network such as 10.0.0.0/8, 172.16.0.0/12
or 192.168.0.0/16. GeoIP can only look up public IP addresses.
------
This file was generated by running
pandoc --from html --to markdown
Using the pre-generated HTML from
http://dev.maxmind.com/geoip/legacy/mod_geoip2 as the input.
geoip-api-mod_geoip2-1.2.10/README.php 0000664 0000000 0000000 00000001275 12476363444 0017157 0 ustar 00root root 0000000 0000000 To use from PHP, use something like:
GeoIP Country:
GeoIP Region:
GeoIP City:
==================================================
Redirection with PHP
$country_code = apache_note("GEOIP_COUNTRY_CODE");
if ( $country_code == "DE" )
{
header ("Location: http://www.google.de" );
}
else
{
header ("Location: http://www.yoursite.com" );
}
geoip-api-mod_geoip2-1.2.10/mod_geoip.c 0000664 0000000 0000000 00000100240 12476363444 0017607 0 ustar 00root root 0000000 0000000 /* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2004 MaxMind, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* MaxMind (http://www.maxmind.com/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "MaxMind" and "GeoIP" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact support@maxmind.com.
*
* 5. Products derived from this software may not be called "GeoIP",
* nor may "MaxMind" appear in their name, without prior written
* permission of the MaxMind.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
*/
/* This module sets an environment variable to the remote country
* based on the requester's IP address. It uses the GeoIP library
* to lookup the country by IP address.
*/
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"
#include "ap_config.h"
#include "apr_strings.h"
#include "util_script.h"
#include
#include "GeoIP.h"
#include "GeoIPCity.h"
typedef struct {
int GeoIPEnabled;
} geoip_dir_config_rec;
typedef struct {
GeoIP **gips;
int numGeoIPFiles;
char **GeoIPFilenames;
int GeoIPEnabled;
int GeoIPEnableUTF8;
char GeoIPOutput;
int GeoIPFlags;
int *GeoIPFlags2;
int scanProxyHeaders;
int proxyHeaderMode;
char *GeoIPProxyField;
} geoip_server_config_rec;
static const int GEOIP_PROXY_HEADER_MODE_FIRST_IP = 0;
static const int GEOIP_PROXY_HEADER_MODE_LAST_IP = 1;
static const int GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP = 2;
static const int GEOIP_PROXY_HEADER_MODE_DEFAULT = 0;
static const int GEOIP_NONE = 0;
static const int GEOIP_DEFAULT = 1;
static const int GEOIP_NOTES = 2;
static const int GEOIP_ENV = 4;
static const int GEOIP_REQUEST = 8;
static const int GEOIP_ALL = 14;
static const int GEOIP_INIT = 15;
static const int GEOIP_UNKNOWN = -1;
char metrocodestr[100];
char areacodestr[100];
char latstr[100];
char lonstr[100];
const char *netspeedstring;
module AP_MODULE_DECLARE_DATA geoip_module;
uint32_t _private_ipv4_networks[] = {
167772160U, 184549375U, // 10.0.0.0/8
1681915904U, 1686110207U, // 100.64.0.0/10
2130706432U, 2147483647U, // 127.0.0.0/8
2886729728U, 2887778303U, // 172.16.0.0/12
3221225984U, 3221226239U, // 192.0.2.0/24
3227017984U, 3227018239U, // 192.88.99.0/24
3232235520U, 3232301055U, // 192.168.0.0/16
2851995648U, 2852061183U, // 169.254.0.0/16
0U, 0U
};
static int _is_private(uint32_t ipnum)
{
uint32_t min, max;
uint32_t *p = _private_ipv4_networks;
while ((min = *p++)) {
max = *p++;
if (ipnum < min || ipnum > max) {
continue;
}
return 1;
}
return 0;
}
char *_get_ip_from_xff(request_rec *r, const char *xffheader)
{
char *xff = apr_pstrdup(r->pool, xffheader);
char *xff_ip, *break_ptr;
uint32_t ipnum;
if (xff) {
for (xff_ip = strtok_r(xff, " \t,", &break_ptr); xff_ip;
xff_ip = strtok_r(NULL, " \t,", &break_ptr)) {
if (1 != inet_pton(AF_INET, xff_ip, &ipnum)) {
continue;
}
ipnum = htonl(ipnum);
if (!_is_private(ipnum)) {
char *found = apr_pstrdup(r->pool, xff_ip);
return found;
}
}
}
return NULL;
}
/* create a disabled directory entry */
static void *geoip_create_dir_config(apr_pool_t * p, char *d)
{
geoip_dir_config_rec *dcfg;
dcfg =
(geoip_dir_config_rec *)apr_pcalloc(p, sizeof(geoip_dir_config_rec));
dcfg->GeoIPEnabled = 0;
return dcfg;
}
static apr_status_t geoip_cleanup(void *cfgdata)
{
int i;
geoip_server_config_rec *cfg = (geoip_server_config_rec *)cfgdata;
if (cfg->gips) {
for (i = 0; i < cfg->numGeoIPFiles; i++) {
if (cfg->gips[i]) {
GeoIP_delete(cfg->gips[i]);
cfg->gips[i] = NULL;
}
}
}
return APR_SUCCESS;
}
/* initialize geoip any server ( any virtual server! ) */
static void geoip_server_init(apr_pool_t * p, server_rec * s)
{
geoip_server_config_rec *cfg;
int i;
while (s) {
cfg = (geoip_server_config_rec *)
ap_get_module_config(s->module_config, &geoip_module);
if (!cfg->gips) {
if (cfg->GeoIPFilenames != NULL) {
cfg->gips = apr_pcalloc(p, sizeof(GeoIP *) * cfg->numGeoIPFiles);
for (i = 0; i < cfg->numGeoIPFiles; i++) {
cfg->gips[i] =
GeoIP_open(cfg->GeoIPFilenames[i],
(cfg->GeoIPFlags2[i] ==
GEOIP_UNKNOWN) ? cfg->GeoIPFlags
: cfg->GeoIPFlags2[i]);
if (cfg->gips[i]) {
if (cfg->GeoIPEnableUTF8) {
GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
}
} else {
ap_log_error(
APLOG_MARK, APLOG_ERR, 0,
s,
"[mod_geoip]: Error while opening data file %s",
cfg->GeoIPFilenames[i]);
continue;
}
}
} else {
cfg->gips = apr_pcalloc(p, sizeof(GeoIP *));
cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
if (!cfg->gips[0]) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"[mod_geoip]: Error while opening data file");
}
cfg->numGeoIPFiles = 1;
}
apr_pool_cleanup_register(p, (void *)cfg, geoip_cleanup,
geoip_cleanup);
}
s = s->next;
}
}
static void geoip_child_init(apr_pool_t * p, server_rec * s)
{
geoip_server_config_rec *cfg;
int i, flags;
while (s) {
cfg = (geoip_server_config_rec *)
ap_get_module_config(s->module_config, &geoip_module);
if (cfg->gips) {
if (cfg->GeoIPFilenames != NULL) {
for (i = 0; i < cfg->numGeoIPFiles; i++) {
flags =
(cfg->GeoIPFlags2[i] ==
GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i];
if (cfg->gips[i]) {
GeoIP_delete(cfg->gips[i]);
}
cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], flags);
if (cfg->gips[i]) {
if (cfg->GeoIPEnableUTF8) {
GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
}
} else {
ap_log_error(
APLOG_MARK, APLOG_ERR, 0,
s,
"[mod_geoip]: Error while opening data file %s",
cfg->GeoIPFilenames[i]);
continue;
}
}
} else {
if (cfg->gips[0]) {
GeoIP_delete(cfg->gips[0]);
}
cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
if (!cfg->gips[0]) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"[mod_geoip]: Error while opening data file");
}
cfg->numGeoIPFiles = 1;
}
apr_pool_cleanup_register(p, (void *)cfg, geoip_cleanup,
geoip_cleanup);
}
s = s->next;
}
}
/* map into the first apache */
static int
geoip_post_config(apr_pool_t * p, apr_pool_t * plog,
apr_pool_t * ptemp, server_rec * s)
{
geoip_server_init(p, s);
return OK;
}
static int geoip_header_parser(request_rec * r);
static int geoip_post_read_request(request_rec * r)
{
geoip_server_config_rec *cfg;
cfg = ap_get_module_config(r->server->module_config, &geoip_module);
if (!cfg) {
return DECLINED;
}
if (!cfg->GeoIPEnabled) {
return DECLINED;
}
return geoip_header_parser(r);
}
static int geoip_per_dir(request_rec * r)
{
geoip_dir_config_rec *dcfg;
geoip_server_config_rec *cfg =
ap_get_module_config(r->server->module_config, &geoip_module);
if (cfg && cfg->GeoIPEnabled) {
return DECLINED;
}
dcfg = ap_get_module_config(r->per_dir_config, &geoip_module);
if (!dcfg) {
return DECLINED;
}
if (!dcfg->GeoIPEnabled) {
return DECLINED;
}
return geoip_header_parser(r);
}
char *_get_client_ip(request_rec * r)
{
# if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER == 4
return r->useragent_ip;
# else
return r->connection->remote_ip;
#endif
}
static void geoip_say(geoip_server_config_rec * cfg, request_rec * r,
const char *key, const char *value)
{
if (value) {
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_set(r->notes, key, value);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_set(r->subprocess_env, key, value);
}
if (cfg->GeoIPOutput & GEOIP_REQUEST) {
apr_table_set(r->headers_in, key, value);
}
}
}
static int geoip_header_parser(request_rec * r)
{
char *orgorisp;
char *ipaddr;
short int country_id;
const char *continent_code;
const char *country_code;
const char *country_name;
const char *region_name = NULL;
geoip_server_config_rec *cfg;
unsigned char databaseType;
GeoIPRecord *gir;
GeoIPRegion *giregion;
int i;
int netspeed;
/* For splitting proxy headers */
char *ipaddr_ptr = NULL;
char *comma_ptr;
cfg = ap_get_module_config(r->server->module_config, &geoip_module);
if (!cfg) {
return DECLINED;
}
if (!cfg->scanProxyHeaders) {
ipaddr = _get_client_ip(r);
} else {
ap_add_common_vars(r);
if (cfg->GeoIPProxyField) {
ipaddr_ptr =
(char *)apr_table_get(r->headers_in, cfg->GeoIPProxyField);
} else if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) {
ipaddr_ptr =
(char *)apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP");
} else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) {
ipaddr_ptr =
(char *)apr_table_get(r->subprocess_env,
"HTTP_X_FORWARDED_FOR");
} else if (apr_table_get(r->headers_in, "X-Forwarded-For")) {
ipaddr_ptr =
(char *)apr_table_get(r->headers_in, "X-Forwarded-For");
} else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) {
ipaddr_ptr =
(char *)apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR");
}
if (!ipaddr_ptr) {
ap_log_error(
APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
r->server,
"[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR.");
ipaddr = _get_client_ip(r);
} else {
/* Found XFF like header */
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr);
if (cfg->proxyHeaderMode ==
GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP) {
ipaddr = _get_ip_from_xff(r, ipaddr_ptr);
if (!ipaddr) {
ipaddr = _get_client_ip(r);
}
} else {
ipaddr = (char *)apr_pcalloc(r->pool, 8 * 4 + 7 + 1);
/* proxyHeaderMode is
* GEOIP_PROXY_HEADER_MODE_LAST_IP or GEOIP_PROXY_HEADER_MODE_FIRST_IP
*/
/*
* Check to ensure that the HTTP_CLIENT_IP or
* X-Forwarded-For header is not a comma separated
* list of addresses, which would cause mod_geoip to
* return no country code. If the header is a comma
* separated list, return the first IP address in the
* list, which is (hopefully!) the real client IP.
*/
if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_LAST_IP) {
comma_ptr = strrchr(ipaddr_ptr, ',');
if (comma_ptr) {
/* skip over whitespace */
ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t");
}
}
strncpy(ipaddr, ipaddr_ptr, 8 * 4 + 7);
comma_ptr = strchr(ipaddr, ',');
if (comma_ptr != 0) {
*comma_ptr = '\0';
}
}
}
}
geoip_say(cfg, r, "GEOIP_ADDR", ipaddr);
for (i = 0; i < cfg->numGeoIPFiles; i++) {
/*
* skip database handles that can not be opned for some
* reason
*/
if (cfg->gips[i] == NULL) {
continue;
}
databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1; /* -1 is "magic value"
* in case file not
* found */
switch (databaseType) {
case GEOIP_NETSPEED_EDITION_REV1:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
geoip_say(cfg, r, "GEOIP_NETSPEED", orgorisp);
free(orgorisp);
break;
case GEOIP_NETSPEED_EDITION:
netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr);
if (netspeed == GEOIP_UNKNOWN_SPEED) {
netspeedstring = "unknown";
} else if (netspeed == GEOIP_DIALUP_SPEED) {
netspeedstring = "dialup";
} else if (netspeed == GEOIP_CABLEDSL_SPEED) {
netspeedstring = "cabledsl";
} else if (netspeed == GEOIP_CORPORATE_SPEED) {
netspeedstring = "corporate";
}
geoip_say(cfg, r, "GEOIP_NETSPEED", netspeedstring);
break;
case GEOIP_COUNTRY_EDITION_V6:
/* Get the Country ID */
country_id = GeoIP_id_by_addr_v6(cfg->gips[i], ipaddr);
if (country_id > 0) {
/* Lookup the Code and the Name with the ID */
continent_code = GeoIP_country_continent[country_id];
country_code = GeoIP_country_code[country_id];
country_name = GeoIP_country_name[country_id];
if (cfg->numGeoIPFiles == 0) {
cfg->numGeoIPFiles = 0;
}
if (cfg->GeoIPFilenames == 0) {
cfg->GeoIPFilenames = 0;
}
/* Set it for our user */
geoip_say(cfg, r, "GEOIP_CONTINENT_CODE_V6", continent_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_CODE_V6", country_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_NAME_V6", country_name);
}
break;
case GEOIP_COUNTRY_EDITION:
/* Get the Country ID */
country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr);
if (country_id > 0) {
/* Lookup the Code and the Name with the ID */
continent_code = GeoIP_country_continent[country_id];
country_code = GeoIP_country_code[country_id];
country_name = GeoIP_country_name[country_id];
if (cfg->numGeoIPFiles == 0) {
cfg->numGeoIPFiles = 0;
}
if (cfg->GeoIPFilenames == 0) {
cfg->GeoIPFilenames = 0;
}
/* Set it for our user */
geoip_say(cfg, r, "GEOIP_CONTINENT_CODE", continent_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_CODE", country_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_NAME", country_name);
}
break;
case GEOIP_REGION_EDITION_REV0:
case GEOIP_REGION_EDITION_REV1:
giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr);
if (giregion != NULL) {
if (giregion->country_code[0]) {
region_name =
GeoIP_region_name_by_code
(giregion->country_code, giregion->region);
geoip_say(cfg, r, "GEOIP_COUNTRY_CODE",
giregion->country_code);
country_id = GeoIP_id_by_code(giregion->country_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_NAME",
GeoIP_country_name[country_id]);
geoip_say(cfg, r, "GEOIP_CONTINENT_CODE",
GeoIP_country_continent[country_id]);
}
if (giregion->region[0]) {
geoip_say(cfg, r, "GEOIP_REGION", giregion->region);
}
if (region_name != NULL) {
geoip_say(cfg, r, "GEOIP_REGION_NAME", region_name);
}
GeoIPRegion_delete(giregion);
}
break;
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr);
if (gir != NULL) {
if (gir->country_code != NULL) {
region_name =
GeoIP_region_name_by_code(gir->country_code,
gir->region);
}
sprintf(metrocodestr, "%d", gir->dma_code);
sprintf(areacodestr, "%d", gir->area_code);
geoip_say(cfg, r, "GEOIP_CONTINENT_CODE_V6",
gir->continent_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_CODE_V6", gir->country_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_NAME_V6", gir->country_name);
geoip_say(cfg, r, "GEOIP_REGION_V6", gir->region);
geoip_say(cfg, r, "GEOIP_REGION_NAME_V6", region_name);
geoip_say(cfg, r, "GEOIP_CITY_V6", gir->city);
geoip_say(cfg, r, "GEOIP_DMA_CODE_V6", metrocodestr);
geoip_say(cfg, r, "GEOIP_METRO_CODE_V6", metrocodestr);
geoip_say(cfg, r, "GEOIP_AREA_CODE_V6", areacodestr);
sprintf(latstr, "%f", gir->latitude);
sprintf(lonstr, "%f", gir->longitude);
geoip_say(cfg, r, "GEOIP_LATITUDE_V6", latstr);
geoip_say(cfg, r, "GEOIP_LONGITUDE_V6", lonstr);
geoip_say(cfg, r, "GEOIP_POSTAL_CODE_V6", gir->postal_code);
GeoIPRecord_delete(gir);
}
break;
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr);
if (gir != NULL) {
if (gir->country_code != NULL) {
region_name =
GeoIP_region_name_by_code(gir->country_code,
gir->region);
}
sprintf(metrocodestr, "%d", gir->dma_code);
sprintf(areacodestr, "%d", gir->area_code);
geoip_say(cfg, r, "GEOIP_CONTINENT_CODE", gir->continent_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_CODE", gir->country_code);
geoip_say(cfg, r, "GEOIP_COUNTRY_NAME", gir->country_name);
geoip_say(cfg, r, "GEOIP_REGION", gir->region);
geoip_say(cfg, r, "GEOIP_REGION_NAME", region_name);
geoip_say(cfg, r, "GEOIP_CITY", gir->city);
geoip_say(cfg, r, "GEOIP_DMA_CODE", metrocodestr);
geoip_say(cfg, r, "GEOIP_METRO_CODE", metrocodestr);
geoip_say(cfg, r, "GEOIP_AREA_CODE", areacodestr);
sprintf(latstr, "%f", gir->latitude);
sprintf(lonstr, "%f", gir->longitude);
geoip_say(cfg, r, "GEOIP_LATITUDE", latstr);
geoip_say(cfg, r, "GEOIP_LONGITUDE", lonstr);
geoip_say(cfg, r, "GEOIP_POSTAL_CODE", gir->postal_code);
GeoIPRecord_delete(gir);
}
break;
case GEOIP_ORG_EDITION:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
geoip_say(cfg, r, "GEOIP_ORGANIZATION", orgorisp);
free(orgorisp);
break;
case GEOIP_ISP_EDITION:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
geoip_say(cfg, r, "GEOIP_ISP", orgorisp);
free(orgorisp);
break;
case GEOIP_DOMAIN_EDITION:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
geoip_say(cfg, r, "GEOIP_DOMAIN", orgorisp);
free(orgorisp);
break;
}
}
return OK;
}
static const char *geoip_scanproxyfield(cmd_parms * cmd, void *dummy,
const char *field)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(
cmd->server->module_config, &geoip_module);
if (!field) {
return NULL;
}
conf->GeoIPProxyField = (char *)apr_pstrdup(cmd->pool, field);
return NULL;
}
static const char *geoip_use_first_non_private_x_forwarded_for_ip(cmd_parms *
cmd,
void *dummy,
int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(
cmd->server->module_config, &geoip_module);
if (!conf) {
return "mod_geoip: server structure not allocated";
}
conf->proxyHeaderMode =
arg ? GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP :
GEOIP_PROXY_HEADER_MODE_DEFAULT;
return NULL;
}
static const char *geoip_use_first_x_forwarded_for_ip(cmd_parms * cmd,
void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(
cmd->server->module_config, &geoip_module);
if (!conf) {
return "mod_geoip: server structure not allocated";
}
conf->proxyHeaderMode =
arg ? GEOIP_PROXY_HEADER_MODE_FIRST_IP :
GEOIP_PROXY_HEADER_MODE_DEFAULT;
return NULL;
}
static const char *geoip_use_last_x_forwarded_for_ip(cmd_parms * cmd,
void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(
cmd->server->module_config, &geoip_module);
if (!conf) {
return "mod_geoip: server structure not allocated";
}
conf->proxyHeaderMode =
arg ? GEOIP_PROXY_HEADER_MODE_LAST_IP : GEOIP_PROXY_HEADER_MODE_DEFAULT;
return NULL;
}
static const char *geoip_scanproxy(cmd_parms * cmd, void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(
cmd->server->module_config, &geoip_module);
if (!conf) {
return "mod_geoip: server structure not allocated";
}
conf->scanProxyHeaders = arg;
return NULL;
}
static const char *set_geoip_enable(cmd_parms * cmd, void *dummy, int arg)
{
geoip_server_config_rec *conf;
/* is per directory config? */
if (cmd->path) {
geoip_dir_config_rec *dcfg = dummy;
dcfg->GeoIPEnabled = arg;
return NULL;
}
/* no then it is server config */
conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!conf) {
return "mod_geoip: server structure not allocated";
}
conf->GeoIPEnabled = arg;
return NULL;
}
static const char *set_geoip_enable_utf8(cmd_parms * cmd, void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(
cmd->server->module_config, &geoip_module);
if (!conf) {
return "mod_geoip: server structure not allocated";
}
conf->GeoIPEnableUTF8 = arg;
return NULL;
}
static const char *set_geoip_filename(cmd_parms * cmd, void *dummy,
const char *filename, const char *arg2)
{
int i;
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(
cmd->server->module_config, &geoip_module);
if (!filename) {
return NULL;
}
i = conf->numGeoIPFiles;
conf->numGeoIPFiles++;
conf->GeoIPFilenames =
realloc(conf->GeoIPFilenames, conf->numGeoIPFiles * sizeof(char *));
conf->GeoIPFilenames[i] = (char *)apr_pstrdup(cmd->pool, filename);
conf->GeoIPFlags2 =
realloc(conf->GeoIPFlags2, conf->numGeoIPFiles * sizeof(int));
if (arg2 == NULL) {
conf->GeoIPFlags2[i] = GEOIP_UNKNOWN;
} else if (!strcmp(arg2, "Standard")) {
conf->GeoIPFlags2[i] = GEOIP_STANDARD;
} else if (!strcmp(arg2, "MemoryCache")) {
conf->GeoIPFlags2[i] = GEOIP_MEMORY_CACHE;
} else if (!strcmp(arg2, "CheckCache")) {
conf->GeoIPFlags2[i] = GEOIP_CHECK_CACHE;
} else if (!strcmp(arg2, "IndexCache")) {
conf->GeoIPFlags2[i] = GEOIP_INDEX_CACHE;
} else if (!strcmp(arg2, "MMapCache")) {
conf->GeoIPFlags2[i] = GEOIP_MMAP_CACHE;
}
return NULL;
}
static const char *set_geoip_output_mode(cmd_parms * cmd, void *dummy,
const char *arg)
{
geoip_server_config_rec *cfg =
(geoip_server_config_rec *)ap_get_module_config(cmd->
server->module_config,
&geoip_module);
if (cfg->GeoIPOutput & GEOIP_DEFAULT) {
/* was set to default, clear so can be reset with user specified values */
cfg->GeoIPOutput = GEOIP_NONE;
}
if (!strcmp(arg, "Notes")) {
cfg->GeoIPOutput |= GEOIP_NOTES;
} else if (!strcmp(arg, "Env")) {
cfg->GeoIPOutput |= GEOIP_ENV;
} else if (!strcmp(arg, "Request")) {
cfg->GeoIPOutput |= GEOIP_REQUEST;
} else if (!strcmp(arg, "All")) {
cfg->GeoIPOutput |= GEOIP_ALL;
}
return NULL;
}
static void *make_geoip(apr_pool_t * p, server_rec * d)
{
geoip_server_config_rec *dcfg;
dcfg =
(geoip_server_config_rec *)apr_pcalloc(p,
sizeof
(geoip_server_config_rec));
dcfg->gips = NULL;
dcfg->numGeoIPFiles = 0;
dcfg->GeoIPFilenames = NULL;
dcfg->GeoIPEnabled = 0;
dcfg->GeoIPEnableUTF8 = 0;
dcfg->GeoIPOutput = GEOIP_INIT;
dcfg->GeoIPFlags = GEOIP_STANDARD;
dcfg->GeoIPFlags2 = NULL;
return dcfg;
}
static const command_rec geoip_cmds[] = {
AP_INIT_FLAG("GeoIPScanProxyHeaders",
geoip_scanproxy,
NULL,
RSRC_CONF,
"Get IP from HTTP_CLIENT IP or X-Forwarded-For"),
AP_INIT_TAKE1("GeoIPScanProxyHeaderField",
geoip_scanproxyfield,
NULL,
RSRC_CONF,
"Get IP from this header field, only"),
AP_INIT_FLAG(
"GeoIPUseFirstNonPrivateXForwardedForIP",
geoip_use_first_non_private_x_forwarded_for_ip,
NULL,
RSRC_CONF,
"For more IP's in X-Forwarded-For, use the first non private IP"),
AP_INIT_FLAG("GeoIPUseFirstXForwardedForIP",
geoip_use_first_x_forwarded_for_ip,
NULL,
RSRC_CONF,
"For more IP's in X-Forwarded-For, use the first"),
AP_INIT_FLAG("GeoIPUseLastXForwardedForIP",
geoip_use_last_x_forwarded_for_ip,
NULL,
RSRC_CONF,
"For more IP's in X-Forwarded-For, use the last"),
AP_INIT_FLAG("GeoIPEnable",
set_geoip_enable,
NULL,
RSRC_CONF | OR_FILEINFO,
"Turn on mod_geoip"),
AP_INIT_FLAG("GeoIPEnableUTF8",
set_geoip_enable_utf8,
NULL,
RSRC_CONF,
"Turn on utf8 characters for city names"),
AP_INIT_TAKE12("GeoIPDBFile",
set_geoip_filename,
NULL,
RSRC_CONF,
"Path to GeoIP Data File"),
AP_INIT_ITERATE("GeoIPOutput",
set_geoip_output_mode,
NULL,
RSRC_CONF,
"Specify output method(s)"),
{ NULL }
};
static void geoip_register_hooks(apr_pool_t * p)
{
/* make sure we run before mod_rewrite's handler */
static const char *const aszSucc[] =
{ "mod_setenvif.c", "mod_rewrite.c", NULL };
/* we have two entry points, the header_parser hook, right before
* the authentication hook used for Dirctory specific enabled geoiplookups
* or right before directory rewrite rules.
*/
ap_hook_header_parser(geoip_per_dir, NULL, aszSucc, APR_HOOK_FIRST);
/* and the servectly wide hook, after reading the request. Perfecly
* suitable to serve serverwide mod_rewrite actions
*/
ap_hook_post_read_request(geoip_post_read_request, NULL, aszSucc,
APR_HOOK_MIDDLE);
/* setup our childs GeoIP database once for every child */
ap_hook_child_init(geoip_child_init, NULL, NULL, APR_HOOK_MIDDLE);
/* static const char * const list[]={ "mod_geoip.c", NULL }; */
/* mmap the database(s) into the master process */
ap_hook_post_config(geoip_post_config, NULL, NULL, APR_HOOK_MIDDLE);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA geoip_module = {
STANDARD20_MODULE_STUFF,
geoip_create_dir_config, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
make_geoip, /* create per-server config structures */
NULL, /* merge per-server config structures */
geoip_cmds, /* table of config file commands */
geoip_register_hooks /* register hooks */
};