From 120a4b5f8100bf4477e1b024a2c65e760f87ac14 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 9 May 2017 17:39:59 +0300 Subject: Properly convert non-string values on output; improve documentation --- src/vmod_geoip.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/vmod_geoip.vcc | 27 ++++++++++++++++++++- 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/vmod_geoip.c b/src/vmod_geoip.c index 6ad23e2..fd85030 100644 --- a/src/vmod_geoip.c +++ b/src/vmod_geoip.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "vcl.h" #include "vrt.h" #include "vcc_if.h" @@ -94,8 +95,70 @@ conv_utf_string (struct ws *ws, MMDB_entry_data_s *dptr) 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); +} + +static char * +conv_uint32(struct ws *ws, MMDB_entry_data_s *dptr) +{ + return wsprintf(ws, "%" PRIu32, dptr->uint32); +} + +static char * +conv_int32(struct ws *ws, MMDB_entry_data_s *dptr) +{ + return wsprintf(ws, "%" PRIi32, dptr->int32); +} + +static char * +conv_bool(struct ws *ws, MMDB_entry_data_s *dptr) +{ + return wsprintf(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); +} + +static char * +conv_float(struct ws *ws, MMDB_entry_data_s *dptr) +{ + return wsprintf(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_UTF8_STRING] = conv_utf_string, + [MMDB_DATA_TYPE_UINT16] = conv_uint16, + [MMDB_DATA_TYPE_UINT32] = conv_uint32, + [MMDB_DATA_TYPE_INT32] = conv_int32, + [MMDB_DATA_TYPE_BOOLEAN] = conv_bool, + [MMDB_DATA_TYPE_DOUBLE] = conv_double, + [MMDB_DATA_TYPE_FLOAT] = conv_float }; static char * @@ -125,7 +188,8 @@ lookup_geoip_database(struct ws *ws, if (!result.found_entry) return NULL; - rc = MMDB_aget_value(&result.entry, &entry_data, (const char * const* const) path); + 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)); @@ -140,7 +204,8 @@ lookup_geoip_database(struct ws *ws, && entry_conv[entry_data.type]) { retval = entry_conv[entry_data.type] (ws, &entry_data); } else - retval = NULL; + retval = wsprintf(ws, "[%s: can't format %s of type %d]", + ipstr, pathstr, entry_data.type); return retval; } diff --git a/src/vmod_geoip.vcc b/src/vmod_geoip.vcc index 5e2c85e..700cdb3 100644 --- a/src/vmod_geoip.vcc +++ b/src/vmod_geoip.vcc @@ -22,8 +22,33 @@ $Function STRING get(PRIV_VCL, STRING 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. + keys separated by dots. If the lookup path is found, the function returns + the requested value converted to string. Otherwise, **NULL** is returned. + The following data types can be represented as string: + + - utf8_string + - int32 + - uint16 + - uint32 + - boolean + (**0** for *false*, **1** for *true*) + - double + (formatted using **%g**) + - float + (formatted using **%g**) + + 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 :: -- cgit v1.2.1