aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-07-26 10:17:24 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-07-26 10:17:24 +0300
commit72f4a1452469501b945aee79b97bbe456858f44d (patch)
tree007d7fe41b526e0323d3a30caaef54594839832a
parent02bc62f6f7bbffb26e3bb7dd4a9b053b98dc3dd6 (diff)
downloadvmod-geoip-72f4a1452469501b945aee79b97bbe456858f44d.tar.gz
vmod-geoip-72f4a1452469501b945aee79b97bbe456858f44d.tar.bz2
Change IP argument type
* src/vmod_geoip.vcc (get, country_code) (city_name): Pass IP argument, instead of STRING * src/vmod_geoip.c: Ditto. Use VSLb and WS_Printf instead of own functions.
-rw-r--r--src/vmod_geoip.c126
-rw-r--r--src/vmod_geoip.vcc14
2 files changed, 67 insertions, 73 deletions
diff --git a/src/vmod_geoip.c b/src/vmod_geoip.c
index fd85030..b7e30ba 100644
--- a/src/vmod_geoip.c
+++ b/src/vmod_geoip.c
@@ -7,47 +7,58 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <inttypes.h>
#include "vcl.h"
#include "vrt.h"
+#include "vtcp.h"
+#include "vsa.h"
#include "vcc_if.h"
-#include "bin/varnishd/cache/cache.h"
+#include "cache/cache.h"
#include <maxminddb.h>
#include <assert.h>
#define DEFAULT_DIR "/usr/share/GeoIP"
#define DEFAULT_FILE "GeoLite2-City.mmdb"
#define DEFAULT_DATABASE DEFAULT_DIR "/" DEFAULT_FILE
struct geoip_config {
char *database;
};
+static void
+free_conf(void *data)
+{
+ struct geoip_config *cfg = data;
+ free(data);
+}
+
int
geoip_event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
{
if (e == VCL_EVENT_LOAD) {
struct geoip_config *conf = calloc(1, sizeof(*conf));
AN(conf);
priv->priv = conf;
+ priv->free = free_conf;
}
return 0;
}
void
vmod_init(VRT_CTX, struct vmod_priv *priv, const char *dir)
{
struct geoip_config *conf = priv->priv;
struct stat st;
char *name;
- if (stat (dir, &st)) {
- fprintf (stderr, "geoip.init: can't stat \"%s\": %s\n",
- dir, strerror (errno));
- abort ();
+ if (stat(dir, &st)) {
+ VSLb(ctx->vsl, SLT_Error,
+ "geoip.init: can't stat \"%s\": %s",
+ dir, strerror(errno));
+ abort();
}
if (S_ISDIR(st.st_mode)) {
size_t dlen = strlen (dir);
size_t len;
@@ -59,30 +70,32 @@ vmod_init(VRT_CTX, struct vmod_priv *priv, const char *dir)
name[dlen++] = '/';
strcpy (name + dlen, DEFAULT_FILE);
} else if (S_ISREG (st.st_mode)) {
name = strdup (dir);
AN(name);
} else {
- fprintf (stderr, "geoip.init: \"%s\": bad file type\n", dir);
+ VSLb(ctx->vsl, SLT_Error,
+ "geoip.init: \"%s\": bad file type", dir);
abort ();
}
free(conf->database);
conf->database = name;
}
static int
-open_geoip_database(struct geoip_config *conf, MMDB_s *dbptr)
+open_geoip_database(VRT_CTX, struct geoip_config *conf, MMDB_s *dbptr)
{
char *database = conf->database ? conf->database : DEFAULT_DATABASE;
int rc;
rc = MMDB_open(database, MMDB_MODE_MMAP, dbptr);
if (rc != MMDB_SUCCESS) {
- fprintf(stderr, "can't open database \"%s\": %s\n",
- database, MMDB_strerror(rc));
+ VSLb(ctx->vsl, SLT_Error,
+ "can't open database \"%s\": %s",
+ database, MMDB_strerror(rc));
return -1;
}
return 0;
}
static char *
@@ -93,65 +106,45 @@ conv_utf_string (struct ws *ws, MMDB_entry_data_s *dptr)
memcpy(retval, dptr->utf8_string, dptr->data_size);
retval[dptr->data_size] = 0;
return retval;
}
static char *
-wsprintf(struct ws *ws, char const *fmt, ...)
-{
- va_list ap;
- size_t u, n;
- char *p;
-
- va_start(ap, fmt);
- u = WS_Reserve(ws, 0);
- p = ws->f;
- n = vsnprintf(p, u, fmt, ap);
- va_end(ap);
- if (n)
- n++;
- else
- p = NULL;
- WS_Release(ws, n);
- return p;
-}
-
-static char *
conv_uint16(struct ws *ws, MMDB_entry_data_s *dptr)
{
- return wsprintf(ws, "%" PRIu16, dptr->uint16);
+ return WS_Printf(ws, "%" PRIu16, dptr->uint16);
}
static char *
conv_uint32(struct ws *ws, MMDB_entry_data_s *dptr)
{
- return wsprintf(ws, "%" PRIu32, dptr->uint32);
+ return WS_Printf(ws, "%" PRIu32, dptr->uint32);
}
static char *
conv_int32(struct ws *ws, MMDB_entry_data_s *dptr)
{
- return wsprintf(ws, "%" PRIi32, dptr->int32);
+ return WS_Printf(ws, "%" PRIi32, dptr->int32);
}
static char *
conv_bool(struct ws *ws, MMDB_entry_data_s *dptr)
{
- return wsprintf(ws, "%01d", dptr->boolean ? 1 : 0);
+ return WS_Printf(ws, "%01d", dptr->boolean ? 1 : 0);
}
static char *
conv_double(struct ws *ws, MMDB_entry_data_s *dptr)
{
- return wsprintf(ws, "%g", dptr->double_value);
+ return WS_Printf(ws, "%g", dptr->double_value);
}
static char *
conv_float(struct ws *ws, MMDB_entry_data_s *dptr)
{
- return wsprintf(ws, "%g", dptr->float_value);
+ return WS_Printf(ws, "%g", dptr->float_value);
}
static char *(*entry_conv[]) (struct ws *, MMDB_entry_data_s *) = {
[MMDB_DATA_TYPE_UTF8_STRING] = conv_utf_string,
[MMDB_DATA_TYPE_UINT16] = conv_uint16,
[MMDB_DATA_TYPE_UINT32] = conv_uint32,
@@ -159,57 +152,62 @@ static char *(*entry_conv[]) (struct ws *, MMDB_entry_data_s *) = {
[MMDB_DATA_TYPE_BOOLEAN] = conv_bool,
[MMDB_DATA_TYPE_DOUBLE] = conv_double,
[MMDB_DATA_TYPE_FLOAT] = conv_float
};
static char *
-lookup_geoip_database(struct ws *ws,
- MMDB_s *dbfile, VCL_STRING ipstr,
+lookup_geoip_database(VRT_CTX,
+ MMDB_s *dbfile, VCL_IP ip,
char const *pathstr, char **path)
{
MMDB_lookup_result_s result;
- int gai_error, mmdb_error;
+ int mmdb_error;
int rc;
MMDB_entry_data_s entry_data;
char *retval;
+ const struct sockaddr *sa;
+ socklen_t sl;
+ char ipstr[VTCP_ADDRBUFSIZE];
- result = MMDB_lookup_string(dbfile, ipstr, &gai_error, &mmdb_error);
- if (gai_error) {
- fprintf(stderr, "%s %s: GAI %s\n",
- pathstr, ipstr, gai_strerror(gai_error));
+ if (!(sa = VSA_Get_Sockaddr(ip, &sl)))
return NULL;
- }
+ result = MMDB_lookup_sockaddr(dbfile, sa, &mmdb_error);
if (mmdb_error != MMDB_SUCCESS) {
- fprintf(stderr, "%s %s: MMDB %s\n",
- pathstr, ipstr, MMDB_strerror(mmdb_error));
+ VTCP_name(ip, ipstr, sizeof ipstr, NULL, 0);
+ VSLb(ctx->vsl, SLT_Error,
+ "%s: %s",
+ pathstr, ipstr, MMDB_strerror(mmdb_error));
return NULL;
}
if (!result.found_entry)
return NULL;
rc = MMDB_aget_value(&result.entry, &entry_data,
(const char * const* const) path);
if (rc != MMDB_SUCCESS) {
- fprintf(stderr, "%s %s: MMDB_aget_value %s\n",
- pathstr, ipstr, MMDB_strerror(rc));
+ VTCP_name(ip, ipstr, sizeof ipstr, NULL, 0);
+ VSLb(ctx->vsl, SLT_Error,
+ "%s %s: MMDB_aget_value %s",
+ pathstr, ipstr, MMDB_strerror(rc));
return NULL;
}
if (!entry_data.has_data)
return NULL;
if (entry_data.type >= 0
&& entry_data.type <= sizeof (entry_conv) / sizeof (entry_conv[0])
&& entry_conv[entry_data.type]) {
- retval = entry_conv[entry_data.type] (ws, &entry_data);
- } else
- retval = wsprintf(ws, "[%s: can't format %s of type %d]",
- ipstr, pathstr, entry_data.type);
-
+ retval = entry_conv[entry_data.type] (ctx->ws, &entry_data);
+ } else {
+ VTCP_name(ip, ipstr, sizeof ipstr, NULL, 0);
+ retval = WS_Printf(ctx->ws, "[%s: can't format %s of type %d]",
+ ipstr, pathstr, entry_data.type);
+ }
return retval;
}
static char **
split(char const *path)
{
@@ -241,85 +239,85 @@ split(char const *path)
}
retv[j] = NULL;
return retv;
}
VCL_STRING
-vmod_get(VRT_CTX, struct vmod_priv *priv, VCL_STRING ipstr, VCL_STRING path)
+vmod_get(VRT_CTX, struct vmod_priv *priv, VCL_IP ip, VCL_STRING path)
{
struct geoip_config *conf = priv->priv;
MMDB_s dbfile;
char *retval = NULL;
char **pathv;
- if (open_geoip_database(conf, &dbfile))
+ if (open_geoip_database(ctx, conf, &dbfile))
return NULL;
pathv = split(path);
- retval = lookup_geoip_database(ctx->ws, &dbfile, ipstr, path, pathv);
+ retval = lookup_geoip_database(ctx, &dbfile, ip, path, pathv);
free(pathv);
MMDB_close(&dbfile);
return retval;
}
VCL_STRING
-vmod_country_code(VRT_CTX, struct vmod_priv *priv, VCL_STRING ipstr)
+vmod_country_code(VRT_CTX, struct vmod_priv *priv, VCL_IP ip)
{
struct geoip_config *conf = priv->priv;
MMDB_s dbfile;
char *retval = NULL;
static char *country_code_path[] = {
"country",
"iso_code",
NULL
};
- if (open_geoip_database(conf, &dbfile))
+ if (open_geoip_database(ctx, conf, &dbfile))
return NULL;
- retval = lookup_geoip_database(ctx->ws, &dbfile, ipstr,
+ retval = lookup_geoip_database(ctx, &dbfile, ip,
"country.iso_code", country_code_path);
MMDB_close(&dbfile);
return retval;
}
VCL_STRING
-vmod_country_name(VRT_CTX, struct vmod_priv *priv, VCL_STRING ipstr)
+vmod_country_name(VRT_CTX, struct vmod_priv *priv, VCL_IP ip)
{
struct geoip_config *conf = priv->priv;
MMDB_s dbfile;
char *retval = NULL;
static char *country_name_path[] = {
"country",
"names",
"en",
NULL
};
- if (open_geoip_database(conf, &dbfile))
+ if (open_geoip_database(ctx, conf, &dbfile))
return NULL;
- retval = lookup_geoip_database(ctx->ws, &dbfile, ipstr,
+ retval = lookup_geoip_database(ctx, &dbfile, ip,
"country.names.en",
country_name_path);
MMDB_close(&dbfile);
return retval;
}
VCL_STRING
-vmod_city_name(VRT_CTX, struct vmod_priv *priv, VCL_STRING ipstr)
+vmod_city_name(VRT_CTX, struct vmod_priv *priv, VCL_IP ip)
{
struct geoip_config *conf = priv->priv;
MMDB_s dbfile;
char *retval = NULL;
static char *city_name_path[] = {
"city",
"names",
"en",
NULL
};
- if (open_geoip_database(conf, &dbfile))
+ if (open_geoip_database(ctx, conf, &dbfile))
return NULL;
- retval = lookup_geoip_database(ctx->ws, &dbfile, ipstr,
+ retval = lookup_geoip_database(ctx, &dbfile, ip,
"city.names.en",
city_name_path);
MMDB_close(&dbfile);
return retval;
}
diff --git a/src/vmod_geoip.vcc b/src/vmod_geoip.vcc
index ffe024e..d96dc09 100644
--- a/src/vmod_geoip.vcc
+++ b/src/vmod_geoip.vcc
@@ -14,13 +14,13 @@ Description
**/usr/share/GeoIP/GeoLite2-City.mmdb**. This can be changed by
calling **geoip.init** from with the full pathname to the database
as its argument. Normally, it is done in **vcl_init**. The pathname
must exist. If the pathname refers to a directory, **/GeoLite2-City.mmdb**
will be appended to it.
-$Function STRING get(PRIV_VCL, STRING ip, STRING path)
+$Function STRING get(PRIV_VCL, IP ip, STRING path)
Description
Look up in the database a value described by **path** corresponding to the
IP address **ip**. The lookup path must consist of one or more lookup
keys separated by dots. If the lookup path is found, the function returns
the requested value converted to string. Otherwise, **NULL** is returned.
@@ -41,34 +41,30 @@ Description
For types not listed above, the following string is returned:
[*X.X.X.X*: can't format *A.B.C* of type *N*]
where *X.X.X.X* stands for IP address, *A.B.C* for lookup path, and
*N* for the data type in decimal.
-
- Note that the function takes as its argument the IP address in string
- representation. Care should be taken to ensure proper conversion when
- passing IP addresses, as shown in the example below.
Example
::
- set req.http.X-Country-Code = geoip.get("" + client.ip,
+ set req.http.X-Country-Code = geoip.get(client.ip,
"country.name.en");
-$Function STRING country_code(PRIV_VCL, STRING ip)
+$Function STRING country_code(PRIV_VCL, IP ip)
Description
Returns the ISO 3166-1 alpha-2 country code corresponding to the **ip**.
Equivalent to geoip.get(ip, "country.iso_code").
-$Function STRING country_name(PRIV_VCL, STRING ip)
+$Function STRING country_name(PRIV_VCL, IP ip)
Description
Returns the English name of the country corresponding to **ip**.
Equivalent to geoip.get(ip, "country.names.en"),
-$Function STRING city_name(PRIV_VCL, STRING ip)
+$Function STRING city_name(PRIV_VCL, IP ip)
Description
Returns the name of the city where **ip** is located.
Equivalent to geoip.get(ip, "city.names.en").

Return to:

Send suggestions and report system problems to the System administrator.