1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# Maxmind GeoIP2 API bindings
# Copyright (c) 2013 Timo Teräs
# GPLv2 applies
# Use from your VCL by adding to your vcl_recv():
# call maxminddb_lookup;
# You also need to modify the cc_command parameter to include
# Maxmind database library (-lmaxminddb). In Alpine Linux this is
# done by uncomminting the relevant VARNISHD_PLUGIN_CFLAGS line in
# /etc/conf.d/varnishd.
C{
#include <maxminddb.h>
#include <string.h>
static MMDB_s mmdb;
static void __attribute__((constructor)) __geoip_on_load(void)
{
if (MMDB_open("/var/lib/libmaxminddb/GeoLite2-City.mmdb", MMDB_MODE_MMAP, &mmdb) != MMDB_SUCCESS)
mmdb.filename = NULL;
}
static void __attribute__((destructor)) __geoip_on_unload(void)
{
if (mmdb.filename != NULL)
MMDB_close(&mmdb);
}
static inline void __geoip_set_header(struct sess *sp, const char *hdr, MMDB_lookup_result_s *res, const char * const* path)
{
MMDB_entry_data_s entry;
const char *value = "FAIL";
char buf[64];
int s;
if (!res->found_entry)
goto set_and_exit;
s = MMDB_aget_value(&res->entry, &entry, path);
if (s != MMDB_SUCCESS || !entry.has_data)
goto set_and_exit;
if (entry.type != MMDB_DATA_TYPE_UTF8_STRING || entry.data_size+1 >= sizeof(buf))
goto set_and_exit;
memcpy(buf, entry.utf8_string, entry.data_size);
buf[entry.data_size] = 0;
value = buf;
set_and_exit:
VRT_SetHdr(sp, HDR_REQ, hdr, value, vrt_magic_string_end);
}
static void __geoip_set_headers(struct sess *sp)
{
static const char *continent_path[] = { "continent", "code", NULL };
static const char *country_path[] = { "country", "iso_code", NULL };
MMDB_lookup_result_s res = {0};
int e = MMDB_FILE_OPEN_ERROR;
if (mmdb.filename != NULL)
res = MMDB_lookup_sockaddr(&mmdb, (struct sockaddr*) VRT_r_client_ip(sp), &e);
if (e != MMDB_SUCCESS)
VRT_SetHdr(sp, HDR_REQ, "\016X-GeoIP-Error:", MMDB_strerror(e), vrt_magic_string_end);
__geoip_set_header(sp, "\022X-GeoIP-Continent:", &res, continent_path);
__geoip_set_header(sp, "\020X-GeoIP-Country:", &res, country_path);
}
}C
sub maxminddb_lookup {
C{ __geoip_set_headers(sp); }C
}
|