static void ntree_dump_recurse(const ntree_t* tree, const unsigned bitdepth, const unsigned offset, struct in6_addr ipv6) { dmn_assert(tree); const nnode_t* this_node = &tree->store[offset]; ntree_dump_rec_sub(tree, bitdepth, this_node->zero, ipv6); SETBIT_v6(ipv6.s6_addr, 127 - bitdepth); ntree_dump_rec_sub(tree, bitdepth, this_node->one, ipv6); }
F_NONNULL static void geoip2_list_xlate_recurse(geoip2_t* db, nlist_t* nl, struct in6_addr ip, unsigned depth, const uint32_t node_count, const uint32_t node_num) { dmn_assert(db); dmn_assert(nl); dmn_assert(depth < 129U); if(!depth) { log_err("plugin_geoip: map '%s': GeoIP2 database '%s': Error while traversing tree nodes: depth too low", db->map_name, db->pathname); siglongjmp(db->jbuf, 1); } // skip v4-like spaces other than canonical compat area if( (depth == 32 && ( !memcmp(ip.s6_addr, start_v4mapped, 12U) || !memcmp(ip.s6_addr, start_siit, 12U) || !memcmp(ip.s6_addr, start_wkp, 12U) )) || (depth == 96U && !memcmp(ip.s6_addr, start_teredo, 4U)) || (depth == 112U && !memcmp(ip.s6_addr, start_6to4, 2U)) ) return; MMDB_search_node_s node; int read_rv = MMDB_read_node(&db->mmdb, node_num, &node); if(read_rv != MMDB_SUCCESS) { log_err("plugin_geoip: map '%s': GeoIP2 database '%s': Error while traversing tree nodes: %s", db->map_name, db->pathname, MMDB_strerror(read_rv)); siglongjmp(db->jbuf, 1); } const uint32_t zero_node_num = node.left_record; const uint32_t one_node_num = node.right_record; const unsigned new_depth = depth - 1U; const unsigned mask = 128U - new_depth; if(zero_node_num >= node_count) nlist_append(nl, ip.s6_addr, mask, geoip2_get_dclist_cached(db, zero_node_num - node_count)); else geoip2_list_xlate_recurse(db, nl, ip, new_depth, node_count, zero_node_num); SETBIT_v6(ip.s6_addr, mask - 1U); if(one_node_num >= node_count) nlist_append(nl, ip.s6_addr, mask, geoip2_get_dclist_cached(db, one_node_num - node_count)); else geoip2_list_xlate_recurse(db, nl, ip, new_depth, node_count, one_node_num); }