IP アドレスから位置情報を取得するGeoIP

GeoIP

IP アドレスから位置情報を取得する為のAPI です。国、領域、都市、緯度、および経度の取得をサポートしています。

C言語向けAPI インストール

ソースからビルドする。

cd /usr/local/src
wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP-1.4.6.tar.gz
tar xzvf GeoIP-1.4.6.tar.gz
cd GeoIP-1.4.6
./configure
make
make check
make install

ドキュメントらしいものは無さそうなので、ソースファイルの test/ ディレクトリのサンプルコードか、ライブラリのソースを読むしかなさそう。

データベース更新 (無料版)

インストール先の share/GeoIP/ 以下にデータベースが展開される。

$ ls /usr/bin/share/GeoIP/
GeoIP.dat  GeoLiteCity.dat

配置してある dat ファイルの最新版を手動でダウンロードして入れ替える。GeoLiteCity.dat についてはデフォルトでは含まれていないので自分で追加する。

国データベース

wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz
cp GeoIP.dat /usr/bin/share/GeoIP/

都市 (緯度,経度) データベース

wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
cp GeoListCity.dat /usr/bin/share/GeoIP/

コマンドラインから利用する方法

geoiplookup コマンドで位置情報を取得できる。

$ geoiplookup www.google.com
GeoIP Country Edition: US, United States
$ geoiplookup www.google.com -f GeoLiteCity.dat
GeoIP City Edition, Rev 1: US, CA, Mountain View, 94043, 37.419201, -122.057404, 807, 650

C言語からAPI を利用する方法

コンパイル時に GeoIP ライブラリを指定する。

gcc geoip.c -o geoip -lGeoIP

以下の2パターンで利用できる関数が存在する。

  • *_by_name() : ホスト名から位置情報を取得
  • *_by_addr() : IPアドレスから位置情報を取得

都市情報取得

#include <GeoIP.h>
#include <GeoIPCity.h>

static const char * _mk_NA( const char * p ){
    return p ? p : "N/A";
}

int main (int argc, char *argv[]) {
    GeoIP       * gi;
    GeoIPRecord *gir;
    const char  *time_zone = NULL;
    char        **ret;

    const char *host = "www.google.com";
    printf("host: %s\n", host);

    gi = GeoIP_open("GeoLiteCity.dat", GEOIP_INDEX_CACHE);
    gir = GeoIP_record_by_name(gi, host);

    if (gir == NULL) {
        printf("GeoIP record is NULL!\n");
        exit(1);
    }
    ret = GeoIP_range_by_ip(gi, host);
    time_zone = GeoIP_time_zone_by_country_and_region(gir->country_code, gir->region);
    printf("%s\t%s\t%s\t%s\t%s\t%s\t%f\t%f\t%d\t%d\t%s\t%s\t%s\n", host,
        _mk_NA(gir->country_code),
        _mk_NA(gir->region),
        _mk_NA(GeoIP_region_name_by_code(gir->country_code, gir->region)),
        _mk_NA(gir->city),
        _mk_NA(gir->postal_code),
        gir->latitude,
        gir->longitude,
        gir->metro_code,
        gir->area_code,
        _mk_NA(time_zone),
        ret[0],
        ret[1]);
    GeoIP_range_by_ip_delete(ret);
    GeoIPRecord_delete(gir);
    GeoIP_delete(gi);
    return 0;
}

Makefile でビルド

標準と異なるディレクトリにインストールしていろいろ面倒だったので作成してみた。依存関係も make で勝手にやってくれるはず。

# Makefile for GeoIP API

# target name
target = geoip

## GeoIP Config
# API install directory
api_dir = ./api
api_include = ${api_dir}/include
api_lib = ${api_dir}/lib
# Specify Library file
lapi = -lGeoIP
# Include path for GeoIP
Iapi = -I$(api_include)
# Library path for GeoIP
Lapi = -L$(api_lib)

## gcc option
opt = $(Iapi) $(lapi) $(Lapi)
gcc = gcc
## files
src = geoip.c distance.c
objs = $(src:%.c=%.o)
deps = $(src:%.c=%.d)


# Transfer GeoIP library path to linker
$(target): $(objs)
    $(gcc) -o $(target) $(objs) -lm $(opt) -Wl,-rpath=$(api_lib)


.SUFFIXES: .c .d .o
# Create object files
.c.o:
    $(gcc) -o $@ -c $< ${Iapi} ${Lapi}
## Dependency
.c.d:
    $(gcc) -MM $< > $(<:%.c=%.d)
-include $(deps)


.PHONY: clean clean-all
clean:
    rm -f $(objs) $(deps)

clean-all: clean
    rm -f $(target)