コード例 #1
0
ファイル: mmdblookup.c プロジェクト: glensc/libmaxminddb
LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address,
                           const char **lookup_path,
                           int lookup_path_length)
{

    MMDB_lookup_result_s result = lookup_or_die(mmdb, ip_address);
    MMDB_entry_data_list_s *entry_data_list = NULL;

    int exit_code = 0;

    if (result.found_entry) {
        int status;
        if (lookup_path_length) {
            MMDB_entry_data_s entry_data;
            status = MMDB_aget_value(&result.entry, &entry_data,
                                     lookup_path);
            if (MMDB_SUCCESS == status) {
                if (entry_data.offset) {
                    MMDB_entry_s entry =
                    { .mmdb = mmdb, .offset = entry_data.offset };
                    status = MMDB_get_entry_data_list(&entry,
                                                      &entry_data_list);
                } else {
                    fprintf(
                        stdout,
                        "\n  No data was found at the lookup path you provided\n\n");
                }
            }
        } else {
コード例 #2
0
ファイル: tfgeoip.c プロジェクト: jszigetvari/syslog-ng
static void
tf_geoip_maxminddb_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result)
{
  GString **argv = (GString **) args->bufs->pdata;
  TFMaxMindDBState *state = (TFMaxMindDBState *) s;

  int _gai_error, mmdb_error;
  MMDB_lookup_result_s mmdb_result =
    MMDB_lookup_string(state->database, argv[0]->str, &_gai_error, &mmdb_error);

  if (!mmdb_result.found_entry)
    {
      mmdb_problem_to_error(_gai_error, mmdb_error, "tflookup");
      return;
    }

  MMDB_entry_data_s entry_data;
  mmdb_error = MMDB_aget_value(&mmdb_result.entry, &entry_data, (const char *const* const)state->entry_path);
  if (mmdb_error != MMDB_SUCCESS)
    {
      mmdb_problem_to_error(0, mmdb_error, "tfget_value");
      return;
    }

  if (entry_data.has_data)
    append_mmdb_entry_data_to_gstring(result, &entry_data);

  return;
}
コード例 #3
0
ファイル: get_value_t.c プロジェクト: Dmitry666/libmaxminddb
void test_simple_structure(int mode, const char *mode_desc)
{
    const char *filename = "MaxMind-DB-test-decoder.mmdb";
    const char *path = test_database_path(filename);
    MMDB_s *mmdb = open_ok(path, mode, mode_desc);
    free((void *)path);

    const char *ip = "1.1.1.1";
    MMDB_lookup_result_s result =
        lookup_string_ok(mmdb, ip, filename, mode_desc);

    {
        MMDB_entry_data_s entry_data;
        const char *lookup_path[] = { "array", "0", NULL };
        int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
        test_array_0_result(status, entry_data, "MMDB_aget_value");

        status = MMDB_get_value(&result.entry, &entry_data, "array", "0", NULL);
        test_array_0_result(status, entry_data, "MMDB_get_value");

        status = call_vget_value(&result.entry, &entry_data, "array", "0", NULL);
        test_array_0_result(status, entry_data, "MMDB_vget_value");
    }

    {
        MMDB_entry_data_s entry_data;
        const char *lookup_path[] = { "array", "2", NULL };
        int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
        test_array_2_result(status, entry_data, "MMDB_aget_value");

        status = MMDB_get_value(&result.entry, &entry_data, "array", "2", NULL);
        test_array_2_result(status, entry_data, "MMDB_get_value");

        status = call_vget_value(&result.entry, &entry_data, "array", "2", NULL);
        test_array_2_result(status, entry_data, "MMDB_vget_value");
    }

    MMDB_close(mmdb);
    free(mmdb);
}
コード例 #4
0
// lookup an ip address using the maxmind db and return the value
// lookup_path described in this doc: http://maxmind.github.io/MaxMind-DB/
const char *
geo_lookup(MMDB_s *const mmdb_handle, const char *ipstr, const char **lookup_path)
{
    char *data = NULL;
    // Lookup IP in the DB
    int gai_error, mmdb_error;
    MMDB_lookup_result_s result =
        MMDB_lookup_string(mmdb_handle, ipstr, &gai_error, &mmdb_error);

    if (0 != gai_error) {
#if DEBUG
        fprintf(stderr,
            "[INFO] Error from getaddrinfo for %s - %s\n\n",
            ipstr, gai_strerror(gai_error));
#endif
        return NULL;
    }

    if (MMDB_SUCCESS != mmdb_error) {
#if DEBUG
        fprintf(stderr,
            "[ERROR] Got an error from libmaxminddb: %s\n\n",
            MMDB_strerror(mmdb_error));
#endif
        return NULL;
    }

    // Parse results
    MMDB_entry_data_s entry_data;
    int exit_code = 0;

    if (result.found_entry) {
        int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);

        if (MMDB_SUCCESS != status) {
#if DEBUG
            fprintf(
                stderr,
                    "[WARN] Got an error looking up the entry data. Make sure \
 the lookup_path is correct. %s\n",
                    MMDB_strerror(status));
#endif
            exit_code = 4;
            return NULL;
        }
コード例 #5
0
ファイル: gdgeoip2.c プロジェクト: extremeshok/gdnsd
static void geoip2_dcmap_cb(void* data, char* lookup, const unsigned level) {
    dmn_assert(data);

    geoip2_dcmap_cb_data_t* state = data;

    // Explicit out-of-data set from below
    if(state->out_of_data)
        return;

    MMDB_entry_data_s val;

    if(!level) {
        mmdb_lookup_utf8_(GEOIP2_PATH_CONTINENT);
        return;
    }

    if(level == 1U) {
        mmdb_lookup_utf8_(GEOIP2_PATH_COUNTRY);
        // No further data for Country-level databases
        if(!state->db->is_city)
            state->out_of_data = true;
        return;
    }

    if(state->db->city_no_region) {
        mmdb_lookup_utf8_(GEOIP2_PATH_CITY);
        state->out_of_data = true;
        return;
    }

    // We only allow for up to 8-9 subdivision levels
    // (9 will function correctly, but then we won't bother
    //   matching city data after.  8 levels will fully function
    //   and do the city-level at the end if there's not a 9th
    //   level in the database).
    // If any country actually needs more, we'll have to change
    //   the simplistic '0' + subd_level magic below for lookup strings.
    if(level > 11U) {
        state->out_of_data = true;
        return;
    }

    // used to search/fetch subdivision array elements
    dmn_assert(level >= 2U && level <= 11U);
    const unsigned subd_level = level - 2U;
    const char idx[2] = { '0' + subd_level, '\0' };
    const char* path_subd[] = { "subdivisions", &idx[0], "iso_code", NULL };

    // fetch this level of subdivision data if possible
    int mmrv = MMDB_aget_value(&state->entry, &val, path_subd);
    if(mmrv == MMDB_SUCCESS && val.has_data && val.type == MMDB_DATA_TYPE_UTF8_STRING && val.utf8_string) {
        if(lookup) {
            memcpy(lookup, val.utf8_string, val.data_size);
            lookup[val.data_size] = '\0';
        }
    }
    else if(mmrv == MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) {
        // no subdivision data left, or at all to begin with,
        //   switch to city and signal end of data depth
        mmdb_lookup_utf8_(GEOIP2_PATH_CITY);
        state->out_of_data = true;
    }
    else {
        dmn_log_err("plugin_geoip: map %s: Unexpected error fetching GeoIP2City subdivision data (%s)",
            state->db->map_name, MMDB_strerror(mmrv));
        siglongjmp(state->db->jbuf, 1);
    }
}
コード例 #6
0
ファイル: LookupResult.cpp プロジェクト: iSLC/VCMP-SqMod
// ------------------------------------------------------------------------------------------------
SQInteger LookupResult::GetValue(HSQUIRRELVM vm)
{
    const Int32 top = sq_gettop(vm);
    // The lookup result instance
    LookupResult * lookup = nullptr;
    // Attempt to extract the lookup result instance
    try
    {
        lookup = Var< LookupResult * >(vm, 1).value;
    }
    catch (const Sqrat::Exception & e)
    {
        return sq_throwerror(vm, e.what());
    }
    // Do we have a valid lookup result instance?
    if (!lookup)
    {
        return sq_throwerror(vm, "Invalid lookup result instance");
    }
    // See if there's a handle
    else if (!lookup->m_Handle)
    {
        return sq_throwerror(vm, "Invalid Maxmind database reference");
    }
    // See if there's an entry
    else if (!(lookup->m_Result.found_entry))
    {
        return sq_throwerror(vm, "Result does not have an entry");
    }

    typedef std::vector< StackStrF > ArgList;
    // The list of extracted arguments
    ArgList arglist;
    // Extract each argument as a string
    for (SQInteger i = 2; i <= top; ++i)
    {
        arglist.emplace_back(vm, i, false);
        // Did we fail to extract the argument value?
        if (SQ_FAILED(arglist.back().mRes))
        {
            return arglist.back().mRes; // Propagate the error
        }
    }

    typedef std::vector< CSStr > PtrList;
    // The list of pointers to path segments
    PtrList ptrlist;
    // Grab the pointers to argument values
    for (const auto & a : arglist)
    {
        ptrlist.push_back(a.mPtr);
    }
    // Push null to specify the end of the list
    ptrlist.push_back(nullptr);

    MMDB_entry_data_s entry_data;
    // Attempt to retrieve the specified entry data
    const int status = MMDB_aget_value(&(lookup->m_Result.entry), &entry_data, ptrlist.data());
    // Validate the status code
    if (status != MMDB_SUCCESS)
    {
        return sq_throwerror(vm, ToStrF("Unable to get entry data [%s]", MMDB_strerror(status)));
    }
    // Push the resulted list object onto the stack
    try
    {
        ClassType< EntryData >::PushInstance(vm, new EntryData(lookup->m_Handle, entry_data));
    }
    catch (const Sqrat::Exception & e)
    {
        return sq_throwerror(vm, e.what());
    }
    // Specify that we returned a value
    return 1;
}
コード例 #7
0
ファイル: geoip2.c プロジェクト: OpenSIPS/opensips
int geoip2_get_field(lookup_res_t ip_data, char *field, char *buf)
{
	char *path_arr[MAX_PATH_DEPTH+1];
	int i = 0;
	csv_record *path_list, *it;
	str field_str;
	MMDB_entry_data_s entry_data;
	int status;
	int len = 0;

	field_str.s = check_short_fields(field);
	if (!field_str.s)
		field_str.s = field;
	field_str.len = strlen(field_str.s);

	path_list = __parse_csv_record(&field_str, CSV_SIMPLE|CSV_DUP_FIELDS,
					FIELD_PATH_SEP);
	if (!path_list) {
		LM_ERR("bad field:'%s'\n", field);
		return -1;
	}

	for (it = path_list; it; it = it->next) {
		if (i == MAX_PATH_DEPTH) {
			LM_ERR("unknown field:'%s'\n", field);
			goto error;
		}
		path_arr[i++] = it->s.s;
	}
	path_arr[i] = NULL;

	status = MMDB_aget_value(&ip_data.entry, &entry_data,
		(const char *const *const)path_arr);
	if (status != MMDB_SUCCESS) {
		LM_ERR("Failed to get IP data field: %s\n", field);
		goto error;
	}
	if (!entry_data.has_data) {
		LM_ERR("No data for field:'%s'\n", field);
		goto error;
	}

	switch (entry_data.type) {
	case MMDB_DATA_TYPE_UTF8_STRING:
		if (entry_data.data_size > RES_BUF_LEN) {
			LM_ERR("string field to big\n");
			goto error;
		}
		memcpy(buf, entry_data.utf8_string, entry_data.data_size);
		len = entry_data.data_size;
		break;
	case MMDB_DATA_TYPE_DOUBLE:
		len = sprintf(buf, "%f", entry_data.double_value);
		break;
	case MMDB_DATA_TYPE_BYTES:
		if (2*entry_data.data_size > RES_BUF_LEN) {
			LM_ERR("byte field to big\n");
			goto error;
		}
		for (i = 0; i < entry_data.data_size; i++)
			sprintf(buf+2*i, "%x", entry_data.bytes[i]);
		len = 2*entry_data.data_size;
		break;
	case MMDB_DATA_TYPE_UINT16:
		len = sprintf(buf, "%hu", entry_data.uint16);
		break;
	case MMDB_DATA_TYPE_UINT32:
		len = sprintf(buf, "%u", entry_data.uint32);
		break;
	case MMDB_DATA_TYPE_INT32:
		len = sprintf(buf, "%d", entry_data.int32);
		break;
	case MMDB_DATA_TYPE_UINT64:
		len = sprintf(buf, "%lu", entry_data.uint64);
		break;
	case MMDB_DATA_TYPE_BOOLEAN:
		if (entry_data.boolean)
			len = sprintf(buf, "true");
		else
			len = sprintf(buf, "false");
		break;
	case MMDB_DATA_TYPE_FLOAT:
		len = sprintf(buf, "%f", entry_data.float_value);
		break;
	default:
		LM_ERR("Unsupported data type for field: '%s'\n", field);
		goto error;
	}

	free_csv_record(path_list);
	return len;

error:
	free_csv_record(path_list);
	return -1;
}
コード例 #8
0
CAMLprim value mmdb_ml_lookup_path(value ip, value query_list, value mmdb)
{
  CAMLparam3(ip, query_list, mmdb);
  CAMLlocal3(iter_count, caml_clean_result, query_r);

  int total_len = 0, copy_count = 0, gai_error = 0, mmdb_error = 0;
  char *clean_result;
  long int int_result;

  iter_count = query_list;

  unsigned int len = caml_string_length(ip);
  char *as_string = caml_strdup(String_val(ip));
  if (strlen(as_string) != (size_t)len) {
    caml_failwith("Could not copy IP address properly");
  }

  MMDB_s *as_mmdb = (MMDB_s*)Data_custom_val(mmdb);
  MMDB_lookup_result_s *result = caml_stat_alloc(sizeof(*result));
  *result = MMDB_lookup_string(as_mmdb, as_string, &gai_error, &mmdb_error);
  check_error(gai_error, mmdb_error);
  caml_stat_free(as_string);

  while (iter_count != Val_emptylist) {
    total_len++;
    iter_count = Field(iter_count, 1);
  }

  char **query = caml_stat_alloc(sizeof(char *) * (total_len + 1));

  while (query_list != Val_emptylist) {
    query[copy_count] = caml_strdup(String_val(Field(query_list, 0)));
    copy_count++;
    query_list = Field(query_list, 1);
  }
  query[total_len] = NULL;
  MMDB_entry_data_s entry_data;

  int status = MMDB_aget_value(&result->entry,
			       &entry_data,
			       (const char *const *const)query);
  check_status(status);
  check_data(entry_data);
  caml_stat_free(result);
  for (int i = 0; i < copy_count; caml_stat_free(query[i]), i++);
  caml_stat_free(query);
  query_r = caml_alloc(2, 0);
  as_mmdb = NULL;
  switch (entry_data.type) {
  case MMDB_DATA_TYPE_BYTES:
    clean_result = caml_stat_alloc(entry_data.data_size + 1);
    memcpy(clean_result, entry_data.bytes, entry_data.data_size);
    caml_clean_result = caml_copy_string(clean_result);
    caml_stat_free(clean_result);
    goto string_finish;

  case MMDB_DATA_TYPE_UTF8_STRING:
    clean_result = strndup(entry_data.utf8_string, entry_data.data_size);
    caml_clean_result = caml_copy_string(clean_result);
    free(clean_result);
    goto string_finish;

  case MMDB_DATA_TYPE_FLOAT:
    Store_field(query_r, 0, polymorphic_variants.poly_float);
    Store_field(query_r, 1, caml_copy_double(entry_data.float_value));
    goto finish;

  case MMDB_DATA_TYPE_BOOLEAN:
    Store_field(query_r, 0, polymorphic_variants.poly_bool);
    Store_field(query_r, 1, Val_true ? entry_data.boolean : Val_false);
    goto finish;

  case MMDB_DATA_TYPE_DOUBLE:
    Store_field(query_r, 0, polymorphic_variants.poly_float);
    Store_field(query_r, 1, caml_copy_double(entry_data.double_value));
    goto finish;

  case MMDB_DATA_TYPE_UINT16:
    Store_field(query_r, 0, polymorphic_variants.poly_int);
    int_result = Val_long(entry_data.uint16);
    goto int_finish;

  case MMDB_DATA_TYPE_UINT32:
    Store_field(query_r, 0, polymorphic_variants.poly_int);
    int_result = Val_long(entry_data.uint32);
    goto int_finish;

  case MMDB_DATA_TYPE_UINT64:
    Store_field(query_r, 0, polymorphic_variants.poly_int);
    int_result = Val_long(entry_data.uint32);
    goto int_finish;

    // look at /usr/bin/sed -n 1380,1430p src/maxminddb.c
  case MMDB_DATA_TYPE_ARRAY:
  case MMDB_DATA_TYPE_MAP:
    caml_failwith("Can't return a Map or Array yet");
  }

 string_finish:
  Store_field(query_r, 0, polymorphic_variants.poly_string);
  Store_field(query_r, 1, caml_clean_result);
  CAMLreturn(query_r);

 int_finish:
  Store_field(query_r, 1, int_result);
  CAMLreturn(query_r);

 finish:
  CAMLreturn(query_r);
}
コード例 #9
0
static ngx_int_t
ngx_http_geoip2_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
    uintptr_t data)
{
    ngx_http_geoip2_ctx_t   *geoip2 = (ngx_http_geoip2_ctx_t *) data;
    ngx_http_geoip2_db_t    *database = geoip2->database;
    int                     mmdb_error;
    MMDB_entry_data_s       entry_data;
    ngx_http_geoip2_conf_t  *gcf;
    ngx_addr_t              addr;
    ngx_array_t             *xfwd;
    u_char                  *p;

#if (NGX_HAVE_INET6)
    uint8_t address[16], *addressp = address;
#else
    unsigned long address;
#endif

    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip2_module);
    addr.sockaddr = r->connection->sockaddr;
    addr.socklen = r->connection->socklen;

    xfwd = &r->headers_in.x_forwarded_for;

    if (xfwd->nelts > 0 && gcf->proxies != NULL) {
        (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
                                           gcf->proxies, gcf->proxy_recursive);
    }

    switch (addr.sockaddr->sa_family) {
        case AF_INET:
#if (NGX_HAVE_INET6)
            ngx_memset(addressp, 0, 12);
            ngx_memcpy(addressp + 12, &((struct sockaddr_in *)
                                        addr.sockaddr)->sin_addr.s_addr, 4);
            break;

        case AF_INET6:
            ngx_memcpy(addressp, &((struct sockaddr_in6 *)
                                   addr.sockaddr)->sin6_addr.s6_addr, 16);
#else
            address = ((struct sockaddr_in *)addr.sockaddr)->sin_addr.s_addr;
#endif
            break;

        default:
            goto not_found;
    }

#if (NGX_HAVE_INET6)
    if (ngx_memcmp(&address, &database->address, sizeof(address))
        != 0) {
#else
    if (address != database->address) {
#endif
        memcpy(&database->address, &address, sizeof(address));
        database->result = MMDB_lookup_sockaddr(&database->mmdb,
                                           addr.sockaddr, &mmdb_error);

        if (mmdb_error != MMDB_SUCCESS) {
            goto not_found;
        }
    }

    if (!database->result.found_entry
            || MMDB_aget_value(&database->result.entry, &entry_data,
                               geoip2->lookup) != MMDB_SUCCESS) {
        goto not_found;
    }

    if (!entry_data.has_data) {
        goto not_found;
    }

    switch (entry_data.type) {
        case MMDB_DATA_TYPE_UTF8_STRING:
            v->data = (u_char *) entry_data.utf8_string;
            v->len = entry_data.data_size;
            break;
        case MMDB_DATA_TYPE_UINT32:
            p = ngx_palloc(r->pool, NGX_OFF_T_LEN);
            if (p == NULL) {
                return NGX_ERROR;
            }
            v->len = ngx_sprintf(p, "%O", entry_data.uint32) - p;
            v->data = p;
            break;
        default:
            goto not_found;
    }

    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;

    return NGX_OK;

not_found:
    if (geoip2->default_value.len > 0) {
        v->data = geoip2->default_value.data;
        v->len = geoip2->default_value.len;

        v->valid = 1;
        v->no_cacheable = 0;
        v->not_found = 0;
    } else {
        v->not_found = 1;
    }

    return NGX_OK;
}


static void *
ngx_http_geoip2_create_conf(ngx_conf_t *cf)
{
    ngx_pool_cleanup_t      *cln;
    ngx_http_geoip2_conf_t  *conf;

    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip2_conf_t));
    if (conf == NULL) {
        return NULL;
    }

    conf->proxy_recursive = NGX_CONF_UNSET;

    cln = ngx_pool_cleanup_add(cf->pool, 0);
    if (cln == NULL) {
        return NULL;
    }

    cln->handler = ngx_http_geoip2_cleanup;
    cln->data = conf;

    return conf;
}
コード例 #10
0
ファイル: get_value_t.c プロジェクト: Dmitry666/libmaxminddb
void test_nested_structure(int mode, const char *mode_desc)
{
    const char *filename = "MaxMind-DB-test-nested.mmdb";
    const char *path = test_database_path(filename);
    MMDB_s *mmdb = open_ok(path, mode, mode_desc);
    free((void *)path);

    const char *ip = "1.1.1.1";
    MMDB_lookup_result_s result =
        lookup_string_ok(mmdb, ip, filename, mode_desc);

    {
        MMDB_entry_data_s entry_data;
        const char *lookup_path[] =
        { "map1", "map2", "array", "0", "map3", "a", NULL };
        int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
        test_complex_map_a_result(status, entry_data, "MMDB_aget_value");

        status = MMDB_get_value(&result.entry, &entry_data,
                                "map1", "map2", "array", "0", "map3", "a", NULL);
        test_complex_map_a_result(status, entry_data, "MMDB_get_value");

        status = call_vget_value(&result.entry, &entry_data,
                                 "map1", "map2", "array", "0", "map3", "a",
                                 NULL);
        test_complex_map_a_result(status, entry_data, "MMDB_vget_value");
    }

    {
        MMDB_entry_data_s entry_data;
        const char *lookup_path[] =
        { "map1", "map2", "array", "0", "map3", "c", NULL };
        int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
        test_complex_map_c_result(status, entry_data, "MMDB_aget_value");

        status = MMDB_get_value(&result.entry, &entry_data,
                                "map1", "map2", "array", "0", "map3", "c", NULL);
        test_complex_map_c_result(status, entry_data, "MMDB_get_value");

        status = call_vget_value(&result.entry, &entry_data,
                                 "map1", "map2", "array", "0", "map3", "c",
                                 NULL);
        test_complex_map_c_result(status, entry_data, "MMDB_vget_value");
    }

    {
        MMDB_entry_data_s entry_data;
        const char *lookup_path[] =
        { "map1", "map42", "array", "0", "map3", "c", NULL };
        int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
        test_no_result(status, entry_data, "MMDB_aget_value",
                       "map1{map42}{array}[0]{map3}{c}");

        status = MMDB_get_value(&result.entry, &entry_data,
                                "map1", "map42", "array", "0", "map3", "c",
                                NULL);
        test_no_result(status, entry_data, "MMDB_get_value",
                       "map1{map42}{array}[0]{map3}{c}");

        status = call_vget_value(&result.entry, &entry_data,
                                 "map1", "map42", "array", "0", "map3", "c",
                                 NULL);
        test_no_result(status, entry_data, "MMDB_vget_value",
                       "map1{map42}{array}[0]{map3}{c}");
    }

    {
        MMDB_entry_data_s entry_data;
        const char *lookup_path[] =
        { "map1", "map2", "array", "9", "map3", "c", NULL };
        int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
        test_no_result(status, entry_data, "MMDB_aget_value",
                       "map1{map42}{array}[9]{map3}{c}");

        status = MMDB_get_value(&result.entry, &entry_data,
                                "map1", "map2", "array", "9", "map3", "c",
                                NULL);
        test_no_result(status, entry_data, "MMDB_get_value",
                       "map1{map42}{array}[9]{map3}{c}");

        status = call_vget_value(&result.entry, &entry_data,
                                 "map1", "map2", "array", "9", "map3", "c",
                                 NULL);
        test_no_result(status, entry_data, "MMDB_vget_value",
                       "map1{map42}{array}[9]{map3}{c}");
    }

    MMDB_close(mmdb);
    free(mmdb);
}
コード例 #11
0
ファイル: vmod_geoip2.c プロジェクト: elevado/libvmod-geoip2
vmod_geoip2_lookup(VRT_CTX, struct vmod_geoip2_geoip2 *vp,
    VCL_STRING path, VCL_IP addr)
{
	MMDB_lookup_result_s res;
	MMDB_entry_data_s data;
	const struct sockaddr *sa;
	socklen_t addrlen;
	const char **ap, *arrpath[COMPONENT_MAX];
	char buf[LOOKUP_PATH_MAX];
	char *p, *last;
	uint32_t i;
	int error;

	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
	AN(addr);

	if (!vp) {
		VSLb(ctx->vsl, SLT_Error,
		    "geoip2.lookup: Database not open");
		return (NULL);
	}

	if (!path || !*path || strlen(path) >= sizeof(buf)) {
		VSLb(ctx->vsl, SLT_Error,
		    "geoip2.lookup: Invalid or missing path (%s)",
		    path ? path : "NULL");
		return (NULL);
	}

	sa = VSA_Get_Sockaddr(addr, &addrlen);
	AN(sa);

	res = MMDB_lookup_sockaddr(&vp->mmdb, sa, &error);
	if (error != MMDB_SUCCESS) {
		VSLb(ctx->vsl, SLT_Error,
		    "geoip2.lookup: MMDB_lookup_sockaddr: %s",
		    MMDB_strerror(error));
		return (NULL);
	}

	if (!res.found_entry) {
		VSLb(ctx->vsl, SLT_Debug,
		    "geoip2.lookup: No entry for this IP address (%s)",
		    VRT_IP_string(ctx, addr));
		return (NULL);
	}

	strncpy(buf, path, sizeof(buf));

	last = NULL;
	for (p = buf, ap = arrpath; ap < &arrpath[COMPONENT_MAX - 1] &&
	    (*ap = strtok_r(p, "/", &last)) != NULL; p = NULL) {
		if (**ap != '\0')
			ap++;
	}
	*ap = NULL;

	error = MMDB_aget_value(&res.entry, &data, arrpath);
	if (error != MMDB_SUCCESS &&
	    error != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) {
		VSLb(ctx->vsl, SLT_Error,
		    "geoip2.lookup: MMDB_aget_value: %s",
		    MMDB_strerror(error));
		return (NULL);
	}

	if (!data.has_data) {
		VSLb(ctx->vsl, SLT_Debug,
		    "geoip2.lookup: No data for this path (%s)",
		    path);
		return (NULL);
	}

	switch (data.type) {
	case MMDB_DATA_TYPE_BOOLEAN:
		p = WS_Printf(ctx->ws, "%s", data.boolean ?
		    "true" : "false");
		break;

	case MMDB_DATA_TYPE_BYTES:
		p = WS_Alloc(ctx->ws, data.data_size * 2 + 1);
		if (p)
			for (i = 0; i < data.data_size; i++)
				sprintf(&p[i * 2], "%02X", data.bytes[i]);
		break;

	case MMDB_DATA_TYPE_DOUBLE:
		p = WS_Printf(ctx->ws, "%f", data.double_value);
		break;

	case MMDB_DATA_TYPE_FLOAT:
		p = WS_Printf(ctx->ws, "%f", data.float_value);
		break;

	case MMDB_DATA_TYPE_INT32:
		p = WS_Printf(ctx->ws, "%i", data.int32);
		break;

	case MMDB_DATA_TYPE_UINT16:
		p = WS_Printf(ctx->ws, "%u", data.uint16);
		break;

	case MMDB_DATA_TYPE_UINT32:
		p = WS_Printf(ctx->ws, "%u", data.uint32);
		break;

	case MMDB_DATA_TYPE_UINT64:
		p = WS_Printf(ctx->ws, "%ju", (uintmax_t)data.uint64);
		break;

	case MMDB_DATA_TYPE_UTF8_STRING:
		p = WS_Alloc(ctx->ws, data.data_size + 1);
		if (p) {
			memcpy(p, data.utf8_string, data.data_size);
			p[data.data_size] = '\0';
		}
		break;

	default:
		VSLb(ctx->vsl, SLT_Error,
		    "geoip2.lookup: Unsupported data type (%d)",
		    data.type);
		return (NULL);
	}

	if (!p)
		VSLb(ctx->vsl, SLT_Error,
		    "geoip2.lookup: Out of workspace");

	return (p);
}