diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-26 10:17:24 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-26 10:17:24 +0300 |
commit | 72f4a1452469501b945aee79b97bbe456858f44d (patch) | |
tree | 007d7fe41b526e0323d3a30caaef54594839832a | |
parent | 02bc62f6f7bbffb26e3bb7dd4a9b053b98dc3dd6 (diff) | |
download | vmod-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.c | 126 | ||||
-rw-r--r-- | src/vmod_geoip.vcc | 14 |
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"). |