summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorliuxueli <[email protected]>2024-06-19 10:49:21 +0000
committerliuxueli <[email protected]>2024-06-19 10:49:21 +0000
commitcae0281c2fbd77c27e12cbd6e497e44ab1f37f94 (patch)
tree2588b33913f056949d658f8925a7a76056f44a4b /src
parentbfc54a6289d798528303d1923d4c74f3cee84218 (diff)
Feature: performance test case
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/dns_decoder.cpp195
-rw-r--r--src/dns_resource_record.h219
-rw-r--r--src/dns_resource_record_exporter.cpp230
-rw-r--r--src/version.map6
5 files changed, 563 insertions, 89 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a0102cd..9d858c9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,7 +5,7 @@ include_directories(${PROJECT_SOURCE_DIR}/deps/)
aux_source_directory(${PROJECT_SOURCE_DIR}/deps/toml DEPS_SRC)
-set(DNS_DECODER_SRC ${DEPS_SRC} dns_decoder.cpp)
+set(DNS_DECODER_SRC ${DEPS_SRC} dns_decoder.cpp dns_resource_record_exporter.cpp)
add_library(dns_decoder SHARED ${DNS_DECODER_SRC})
set_target_properties(dns_decoder PROPERTIES LINK_FLAGS "-Wl,--version-script=${PROJECT_SOURCE_DIR}/src/version.map")
diff --git a/src/dns_decoder.cpp b/src/dns_decoder.cpp
index 70fba40..23a0ccf 100644
--- a/src/dns_decoder.cpp
+++ b/src/dns_decoder.cpp
@@ -1,19 +1,11 @@
-/*
-**********************************************************************************************
-* File: dns_decoder.c
-* Description:
-* Authors: Liu XueLi <[email protected]>
-* Date: 2024-02-07
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "dns_decoder.h"
+#include "dns_resource_record.h"
+
#include "toml/toml.h"
#include "uthash/uthash.h"
#include "uthash/utlist.h"
@@ -53,17 +45,23 @@ extern "C"
#define TAG_KEY_DNS_SECTION "section"
#define TAG_KEY_DNS_QR "qr"
-#define TAG_KEY_IP_PROTOCOL "ip_protocol"
-#define TAG_VALUE_IP_PROTOCOL_TCP "tcp"
-#define TAG_VALUE_IP_PROTOCOL_UDP "udp"
-
-#define TAG_KEY_IP_VERSION "ip_version"
-#define TAG_VALUE_IP_VERSION_IPV4 "ipv4"
-#define TAG_VALUE_IP_VERSION_IPV6 "ipv6"
+#define TAG_KEY_IPPROTO "ipproto"
+#define TAG_VALUE_IPV4_TCP "ipv4_tcp"
+#define TAG_VALUE_IPV6_TCP "ipv6_tcp"
+#define TAG_VALUE_IPV4_UDP "ipv4_udp"
+#define TAG_VALUE_IPV6_UDP "ipv6_udp"
+#define TAG_VALUE_UNKNOWN "unknown"
#define DNS_MESSAGE_MAGIC 0x53535353
#define DNS_DECODER_TOML_PATH "./etc/dns/dns_decoder.toml"
+#define DNS_CLASS_UNKNOWN 0
+#define DNS_CLASS_IN 1
+#define DNS_CLASS_CS 2
+#define DNS_CLASS_CH 3
+#define DNS_CLASS_HS 4
+#define DNS_CLASS_ANY 255
+
struct dns_message
{
int32_t magic;
@@ -222,7 +220,7 @@ int32_t dns_read_be_u16(uint8_t *payload, size_t payload_sz, size_t *payload_off
if(value!=NULL)
{
- *value=ntohs(*(uint16_t *)(payload+(*payload_offset)));
+ *value=((uint16_t)payload[*payload_offset] << 8) | (uint16_t)payload[*payload_offset+1];
}
(*payload_offset)+=2;
@@ -1156,8 +1154,8 @@ void dns_message_free(struct session *ss, void *expr_str, void *msg_free_arg)
msg->trans_identifier_id=0;
msg->decode_rr_status=DNS_RR_STATUS_INIT;
- memset(&(msg->flag), 0, sizeof(struct dns_flag));
- memset(&(msg->question), 0, sizeof(struct dns_query_question));
+ msg->flag={0};
+ //memset(&(msg->question), 0, sizeof(struct dns_query_question));
msg->rr_capacity_offset=0;
}
@@ -1173,7 +1171,6 @@ void dns_decoder_session_transaction_del(struct dns_decoder_context *per_ss_ctx,
{
if(per_ss_ctx->trans_list_head==NULL || current_trans==NULL)
{
- assert(per_ss_ctx->trans_list_num==0);
return ;
}
@@ -1194,6 +1191,27 @@ void dns_message_transaction_publish(struct session *ss, enum dns_message_type t
session_mq_publish_message(ss, topic_id, msg);
}
+const char *dns_decoder_ipproto_string_get(struct session *ss)
+{
+ enum session_addr_type addr_type=SESSION_ADDR_TYPE_UNKNOWN;
+ session_get0_addr(ss, &addr_type);
+ switch(addr_type)
+ {
+ case SESSION_ADDR_TYPE_IPV4_TCP:
+ return TAG_VALUE_IPV4_TCP;
+ case SESSION_ADDR_TYPE_IPV4_UDP:
+ return TAG_VALUE_IPV4_UDP;
+ case SESSION_ADDR_TYPE_IPV6_TCP:
+ return TAG_VALUE_IPV6_TCP;
+ case SESSION_ADDR_TYPE_IPV6_UDP:
+ return TAG_VALUE_IPV6_UDP;
+ default:
+ break;
+ }
+
+ return TAG_VALUE_UNKNOWN;
+}
+
void dns_decoder_entry(struct session *ss, uint8_t *payload, size_t payload_sz, void *per_session_ctx, void *plugin_env_str)
{
struct dns_header dns_hdr={0};
@@ -1207,13 +1225,9 @@ void dns_decoder_entry(struct session *ss, uint8_t *payload, size_t payload_sz,
size_t payload_offset=DNS_HEADER_SIZE;
int32_t thread_id=session_get_current_thread_id(ss);
+ const char *ipproto=dns_decoder_ipproto_string_get(ss);
struct dns_decoder_plugin_env *plugin_env=(struct dns_decoder_plugin_env *)plugin_env_str;
- enum session_addr_type addr_type=SESSION_ADDR_TYPE_UNKNOWN;
- session_get0_addr(ss, &addr_type);
- const char *ip_version=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV4_UDP) ? TAG_VALUE_IP_VERSION_IPV4 : TAG_VALUE_IP_VERSION_IPV6;
- const char *ip_protocol=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV6_TCP) ? TAG_VALUE_IP_PROTOCOL_TCP : TAG_VALUE_IP_PROTOCOL_UDP;
-
struct dns_message *data_msg=&(plugin_env->per_thread_data_msg[thread_id]);
data_msg->ss=NULL;
data_msg->n_real_answer_rr=0;
@@ -1232,9 +1246,9 @@ void dns_decoder_entry(struct session *ss, uint8_t *payload, size_t payload_sz,
if(data_msg->n_question==1)
{
- size_t tag_offset=4;
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_DNS_QR, TAG_KEY_DNS_SECTION};
- const char *tag_value[tag_offset]={ip_version, ip_protocol, ((dns_hdr.qr==0) ? "query" : "response"), "question"};
+ size_t tag_offset=3;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_DNS_QR, TAG_KEY_DNS_SECTION};
+ const char *tag_value[tag_offset]={ipproto, ((dns_hdr.qr==0) ? "query" : "response"), "question"};
ret=dns_query_question_decode(&(data_msg->question), payload, payload_sz, &payload_offset);
if(ret<DNS_DECODER_FALSE)
{
@@ -1246,6 +1260,7 @@ void dns_decoder_entry(struct session *ss, uint8_t *payload, size_t payload_sz,
dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_OK, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
}
+ int32_t current_trans_idx=0;
struct dns_transaction *current_trans=NULL;
struct dns_decoder_context *per_ss_ctx=(struct dns_decoder_context *)per_session_ctx;
@@ -1259,23 +1274,28 @@ void dns_decoder_entry(struct session *ss, uint8_t *payload, size_t payload_sz,
dns_decoder_session_transaction_del(per_ss_ctx, current_trans);
current_trans=NULL;
- size_t tag_offset=4;
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
- const char *tag_value[tag_offset]={ip_version, ip_protocol, "transaction_end", "duplicate"};
+ size_t tag_offset=3;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
+ const char *tag_value[tag_offset]={ipproto, "transaction_end", "duplicate"};
dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_SEND, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
}
if(current_trans==NULL)
{
- current_trans=(struct dns_transaction *)CALLOC(struct dns_transaction, 1);
- current_trans->trans_idx=(++per_ss_ctx->trans_count);
- current_trans->message_id=message_id;
- dns_decoder_session_transaction_add(per_ss_ctx, current_trans);
- dns_message_transaction_publish(ss, DNS_MESSAGE_TRANSACTION_BEGIN, plugin_env->dns.topic_id, current_trans->trans_idx);
+ current_trans_idx=(++per_ss_ctx->trans_count);
+ if(msg_type==DNS_MESSAGE_QUERY)
+ {
+ current_trans=(struct dns_transaction *)CALLOC(struct dns_transaction, 1);
+ current_trans->trans_idx=current_trans_idx;
+ current_trans->message_id=message_id;
+ dns_decoder_session_transaction_add(per_ss_ctx, current_trans);
+ }
+
+ dns_message_transaction_publish(ss, DNS_MESSAGE_TRANSACTION_BEGIN, plugin_env->dns.topic_id, current_trans_idx);
- size_t tag_offset=4;
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
- const char *tag_value[tag_offset]={ip_version, ip_protocol, "transaction_begin", "normal"};
+ size_t tag_offset=3;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
+ const char *tag_value[tag_offset]={ipproto, "transaction_begin", "normal"};
dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_SEND, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
}
@@ -1285,24 +1305,24 @@ void dns_decoder_entry(struct session *ss, uint8_t *payload, size_t payload_sz,
data_msg->payload_sz=payload_sz;
data_msg->payload_offset=payload_offset;
data_msg->decode_rr_status=DNS_RR_STATUS_INIT;
- data_msg->current_trans_idx=current_trans->trans_idx;
+ data_msg->current_trans_idx=current_trans_idx;
session_mq_publish_message(ss, plugin_env->dns.topic_id, data_msg);
- size_t tag_offset=4;
+ size_t tag_offset=3;
const char *type=((msg_type==DNS_MESSAGE_RESPONSE) ? "response" : "query");
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
- const char *tag_value[tag_offset]={ip_version, ip_protocol, type, "normal"};
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
+ const char *tag_value[tag_offset]={ipproto, type, "normal"};
dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_SEND, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
if(msg_type==DNS_MESSAGE_RESPONSE)
{
- dns_message_transaction_publish(ss, DNS_MESSAGE_TRANSACTION_END, plugin_env->dns.topic_id, current_trans->trans_idx);
+ dns_message_transaction_publish(ss, DNS_MESSAGE_TRANSACTION_END, plugin_env->dns.topic_id, current_trans_idx);
dns_decoder_session_transaction_del(per_ss_ctx, current_trans);
- size_t tag_offset=4;
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
- const char *tag_value[tag_offset]={ip_version, ip_protocol, "transaction_end", "normal"};
+ size_t tag_offset=3;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
+ const char *tag_value[tag_offset]={ipproto, "transaction_end", "normal"};
dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_SEND, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
}
@@ -1312,9 +1332,9 @@ void dns_decoder_entry(struct session *ss, uint8_t *payload, size_t payload_sz,
dns_message_transaction_publish(ss, DNS_MESSAGE_TRANSACTION_END, plugin_env->dns.topic_id, current_trans->trans_idx);
dns_decoder_session_transaction_del(per_ss_ctx, current_trans);
- size_t tag_offset=4;
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
- const char *tag_value[tag_offset]={ip_version, ip_protocol, "transaction_end", "terminate"};
+ size_t tag_offset=3;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
+ const char *tag_value[tag_offset]={ipproto, "transaction_end", "terminate"};
dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_SEND, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
}
}
@@ -1327,17 +1347,13 @@ int dns_decoder_transaction_end_in_closing(struct session *ss, void *per_session
return DNS_DECODER_FALSE;
}
+ const char *ipproto=dns_decoder_ipproto_string_get(ss);
struct dns_decoder_context *per_ss_ctx=(struct dns_decoder_context *)per_session_ctx;
struct dns_decoder_plugin_env *plugin_env=(struct dns_decoder_plugin_env *)plugin_env_str;
- enum session_addr_type addr_type=SESSION_ADDR_TYPE_UNKNOWN;
- session_get0_addr(ss, &addr_type);
- const char *ip_version=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV4_UDP) ? TAG_VALUE_IP_VERSION_IPV4 : TAG_VALUE_IP_VERSION_IPV6;
- const char *ip_protocol=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV6_TCP) ? TAG_VALUE_IP_PROTOCOL_TCP : TAG_VALUE_IP_PROTOCOL_UDP;
-
- size_t tag_offset=4;
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
- const char *tag_value[tag_offset]={ip_version, ip_protocol, "transaction_end", "closing"};
+ size_t tag_offset=3;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_MESSAGE_TYPE, TAG_KEY_MESSAGE_STATUS};
+ const char *tag_value[tag_offset]={ipproto, "transaction_end", "closing"};
dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_SEND, tag_key, tag_value, tag_offset, per_ss_ctx->trans_list_num, session_get_current_thread_id(ss));
struct dns_transaction *current_trans=NULL, *tmp_trans=NULL;
@@ -1450,8 +1466,6 @@ void *dns_decoder_per_session_context_new(struct session *ss, void *plugin_env_s
return NULL;
}
- const char *ip_version=NULL;
- const char *ip_protocol=NULL;
uint16_t sport=0,dport=0;
enum session_addr_type addr_type=SESSION_ADDR_TYPE_UNKNOWN;
struct session_addr *addr=session_get0_addr(ss, &addr_type);
@@ -1462,15 +1476,11 @@ void *dns_decoder_per_session_context_new(struct session *ss, void *plugin_env_s
case SESSION_ADDR_TYPE_IPV4_UDP:
sport=addr->ipv4.sport;
dport=addr->ipv4.dport;
- ip_version=TAG_VALUE_IP_VERSION_IPV4;
- ip_protocol=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP) ? TAG_VALUE_IP_PROTOCOL_TCP : TAG_VALUE_IP_PROTOCOL_UDP;
break;
case SESSION_ADDR_TYPE_IPV6_TCP:
case SESSION_ADDR_TYPE_IPV6_UDP:
sport=addr->ipv6.sport;
dport=addr->ipv6.dport;
- ip_version=TAG_VALUE_IP_VERSION_IPV6;
- ip_protocol=(addr_type==SESSION_ADDR_TYPE_IPV6_TCP) ? TAG_VALUE_IP_PROTOCOL_TCP : TAG_VALUE_IP_PROTOCOL_UDP;
break;
default:
stellar_session_plugin_dettach_current_session(ss);
@@ -1482,9 +1492,11 @@ void *dns_decoder_per_session_context_new(struct session *ss, void *plugin_env_s
{
if((sport==plugin_env->net_port[i]) || (dport==plugin_env->net_port[i]))
{
- const char *tag_key[3]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, "memory"};
- const char *tag_value[3]={ip_version, ip_protocol, "ss_ctx"};
- dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_NEW, tag_key, tag_value, 3, 1, session_get_current_thread_id(ss));
+ size_t tag_offset=2;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, "memory"};
+ const char *ipproto=dns_decoder_ipproto_string_get(ss);
+ const char *tag_value[tag_offset]={ipproto, "ss_ctx"};
+ dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_NEW, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
return CALLOC(struct dns_decoder_context, 1);
}
@@ -1504,16 +1516,13 @@ void dns_decoder_per_session_context_free(struct session *ss, void *per_session_
FREE(per_session_ctx);
- enum session_addr_type addr_type=SESSION_ADDR_TYPE_UNKNOWN;
- session_get0_addr(ss, &addr_type);
- const char *ip_version=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV4_UDP) ? TAG_VALUE_IP_VERSION_IPV4 : TAG_VALUE_IP_VERSION_IPV6;
- const char *ip_protocol=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV6_TCP) ? TAG_VALUE_IP_PROTOCOL_TCP : TAG_VALUE_IP_PROTOCOL_UDP;
-
- const char *tag_key[3]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, "memory"};
- const char *tag_value[3]={ip_version, ip_protocol, "ss_ctx"};
+ size_t tag_offset=2;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, "memory"};
+ const char *ipproto=dns_decoder_ipproto_string_get(ss);
+ const char *tag_value[tag_offset]={ipproto, "ss_ctx"};
struct dns_decoder_plugin_env *plugin_env=(struct dns_decoder_plugin_env *)plugin_env_str;
- dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_FREE, tag_key, tag_value, 3, 1, session_get_current_thread_id(ss));
+ dns_decoder_local_file_counter_incby(plugin_env, LOCAL_STAT_COUNTER_FREE, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(ss));
}
int32_t dns_decoder_config_load(const char *cfg_path, struct dns_decoder_plugin_env *plugin_env)
@@ -1861,7 +1870,22 @@ struct dns_flag *dns_message_header_flag_get0(struct dns_message *msg)
return &(msg->flag);
}
-void dns_message_question_get0(struct dns_message *msg, struct dns_query_question **question, uint16_t *n_question)
+const char *dns_query_question_qname_get0(struct dns_query_question *question)
+{
+ return ((question!=NULL) ? (char *)(question->qname) : NULL);
+}
+
+int32_t dns_query_question_qtype_get0(struct dns_query_question *question)
+{
+ return ((question!=NULL) ? question->qtype : -1);
+}
+
+int32_t dns_query_question_qclass_get0(struct dns_query_question *question)
+{
+ return ((question!=NULL) ? question->qclass : -1);
+}
+
+void dns_message_query_question_get0(struct dns_message *msg, struct dns_query_question **question, uint16_t *n_question)
{
if(msg==NULL || msg->magic!=DNS_MESSAGE_MAGIC || msg->type==DNS_MESSAGE_TRANSACTION_BEGIN || msg->type==DNS_MESSAGE_TRANSACTION_END || msg->n_question==0)
{
@@ -1905,16 +1929,13 @@ int32_t dns_message_resource_record_serialize(struct dns_message *msg)
return DNS_DECODER_FALSE;
}
- enum session_addr_type addr_type=SESSION_ADDR_TYPE_UNKNOWN;
- session_get0_addr(msg->ss, &addr_type);
- const char *ip_version=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV4_UDP) ? TAG_VALUE_IP_VERSION_IPV4 : TAG_VALUE_IP_VERSION_IPV6;
- const char *ip_protocol=(addr_type==SESSION_ADDR_TYPE_IPV4_TCP || addr_type==SESSION_ADDR_TYPE_IPV6_TCP) ? TAG_VALUE_IP_PROTOCOL_TCP : TAG_VALUE_IP_PROTOCOL_UDP;
- size_t tag_offset=4;
- const char *tag_key[tag_offset]={TAG_KEY_IP_VERSION, TAG_KEY_IP_PROTOCOL, TAG_KEY_DNS_QR, TAG_KEY_DNS_SECTION};
+ const char *ipproto=dns_decoder_ipproto_string_get(msg->ss);
+ size_t tag_offset=3;
+ const char *tag_key[tag_offset]={TAG_KEY_IPPROTO, TAG_KEY_DNS_QR, TAG_KEY_DNS_SECTION};
if(msg->type==DNS_MESSAGE_TRANSACTION_BEGIN || msg->type==DNS_MESSAGE_TRANSACTION_END)
{
- const char *tag_value[tag_offset]={ip_version, ip_protocol, ((msg->type==DNS_MESSAGE_TRANSACTION_BEGIN) ? "begin" : "end"), "none"};
+ const char *tag_value[tag_offset]={ipproto, ((msg->type==DNS_MESSAGE_TRANSACTION_BEGIN) ? "begin" : "end"), "none"};
dns_decoder_local_file_counter_incby(msg->plugin_env, LOCAL_STAT_COUNTER_ERROR, tag_key, tag_value, tag_offset, 1, session_get_current_thread_id(msg->ss));
return DNS_DECODER_FALSE;
}
@@ -1945,7 +1966,7 @@ int32_t dns_message_resource_record_serialize(struct dns_message *msg)
if(msg->n_answer_rr>0)
{
- const char *tag_value[tag_offset]={ip_version, ip_protocol, ((msg->type==DNS_MESSAGE_QUERY) ? "query" : "response"), "answer"};
+ const char *tag_value[tag_offset]={ipproto, ((msg->type==DNS_MESSAGE_QUERY) ? "query" : "response"), "answer"};
dns_resource_record_buff_get0(msg->rr_capacity, msg->rr_capacity_sz, &(msg->rr_capacity_offset), &(msg->answer_rr), msg->n_answer_rr, &(msg->n_real_answer_rr));
int32_t ret=dns_resource_record_decode(msg->payload, msg->payload_sz, &(msg->payload_offset), msg->answer_rr, msg->n_real_answer_rr);
if(ret==DNS_DECODER_FALSE)
@@ -1963,7 +1984,7 @@ int32_t dns_message_resource_record_serialize(struct dns_message *msg)
if(msg->n_authority_rr>0)
{
- const char *tag_value[tag_offset]={ip_version, ip_protocol, ((msg->type==DNS_MESSAGE_QUERY) ? "query" : "response"), "authority"};
+ const char *tag_value[tag_offset]={ipproto, ((msg->type==DNS_MESSAGE_QUERY) ? "query" : "response"), "authority"};
dns_resource_record_buff_get0(msg->rr_capacity, msg->rr_capacity_sz, &(msg->rr_capacity_offset), &(msg->authority_rr), msg->n_authority_rr, &(msg->n_real_authority_rr));
int32_t ret=dns_resource_record_decode(msg->payload, msg->payload_sz, &(msg->payload_offset), msg->authority_rr, msg->n_real_authority_rr);
if(ret==DNS_DECODER_FALSE)
@@ -1981,7 +2002,7 @@ int32_t dns_message_resource_record_serialize(struct dns_message *msg)
if(msg->n_additional_rr>0)
{
- const char *tag_value[tag_offset]={ip_version, ip_protocol, ((msg->type==DNS_MESSAGE_QUERY) ? "query" : "response"), "additional"};
+ const char *tag_value[tag_offset]={ipproto, ((msg->type==DNS_MESSAGE_QUERY) ? "query" : "response"), "additional"};
dns_resource_record_buff_get0(msg->rr_capacity, msg->rr_capacity_sz, &(msg->rr_capacity_offset), &(msg->additional_rr), msg->n_additional_rr, &(msg->n_real_additional_rr));
int32_t ret=dns_resource_record_decode(msg->payload, msg->payload_sz, &(msg->payload_offset), msg->additional_rr, msg->n_real_additional_rr);
if(ret==DNS_DECODER_FALSE)
diff --git a/src/dns_resource_record.h b/src/dns_resource_record.h
new file mode 100644
index 0000000..6070b20
--- /dev/null
+++ b/src/dns_resource_record.h
@@ -0,0 +1,219 @@
+#pragma once
+
+#include <stdint.h>
+#include <linux/limits.h>
+#include <stddef.h>
+
+#define DNS_NAME_MAX (NAME_MAX + 1)
+// #define HINFO_NAME_MAX (40 + 1) /* https://www.ietf.org/rfc/rfc1010.txt */
+
+/* RR(resource record) type, defined in https://www.ietf.org/rfc/rfc1035.txt */
+enum dns_rr_type
+{
+ DNS_RR_TYPE_A = 1,
+ DNS_RR_TYPE_NS,
+ DNS_RR_TYPE_MD, /* Obsolete - use MX, rfc973 */
+ DNS_RR_TYPE_MF, /* Obsolete - use MX, rfc973 */
+ DNS_RR_TYPE_CNAME,
+ DNS_RR_TYPE_SOA,
+ DNS_RR_TYPE_MB, /* EXPERIMENTAL, rfc883,rfc2505 */
+ DNS_RR_TYPE_MG, /* EXPERIMENTAL, rfc883,rfc2505 */
+ DNS_RR_TYPE_MR, /* EXPERIMENTAL, rfc883 */
+ DNS_RR_TYPE_NULL, /* EXPERIMENTAL, rfc1035 */
+ DNS_RR_TYPE_WKS, /* Not to be relied upon, rfc1123 */
+ DNS_RR_TYPE_PTR,
+ DNS_RR_TYPE_HINFO,
+ DNS_RR_TYPE_MINFO,
+ DNS_RR_TYPE_MX,
+ DNS_RR_TYPE_TXT,
+ DNS_RR_TYPE_RP,
+ DNS_RR_TYPE_ISDN = 20,
+ DNS_RR_TYPE_AAAA = 28, /* dns_ipv6 */
+ DNS_RR_TYPE_SRV = 33,
+ DNS_RR_TYPE_DNAME = 39,
+ DNS_RR_TYPE_OPT = 41,
+ DNS_RR_TYPE_DS = 43,
+ DNS_RR_TYPE_RRSIG = 46,
+ DNS_RR_TYPE_NSEC,
+ DNS_RR_TYPE_DNSKEY,
+ DNS_RR_TYPE_NSEC3 = 50,
+ DNS_RR_TYPE_NSEC3PARAM,
+ DNS_RR_TYPE_HTTPS = 65,
+ DNS_RR_TYPE_AXFR = 252,
+ DNS_RR_TYPE_MAILB,
+ DNS_RR_TYPE_MAILA, /* Obsolete - see MX */
+ DNS_RR_TYPE_ANY,
+ DNS_RR_TYPE_DLV = 32769, /* DSNSEC Lokkaside Validation */
+ DNS_RR_TYPE_UNKNOWN = 65534
+};
+
+struct dstring
+{
+ size_t value_sz;
+ uint8_t value[DNS_NAME_MAX];
+};
+
+struct rdata_hinfo
+{
+ struct dstring os;
+ struct dstring cpu;
+};
+
+struct rdata_minfo
+{
+ struct dstring rmailbx;
+ struct dstring emailbx;
+};
+
+struct rdata_mx
+{
+ uint16_t preference;
+ struct dstring exchange;
+};
+
+struct rdata_soa
+{
+ struct dstring mname;
+ struct dstring rname;
+ uint32_t serial;
+ uint32_t refresh;
+ uint32_t retry;
+ uint32_t expire;
+ uint32_t minimum;
+};
+
+struct rdata_rp
+{
+ struct dstring txt_rr;
+ struct dstring mailbox;
+};
+
+struct rdata_wks
+{
+ uint8_t protocol;
+ uint32_t addr;
+ uint32_t size;
+ uint8_t *bitmap;
+};
+
+struct rdata_srv
+{
+ uint16_t priority;
+ uint16_t weight;
+ uint16_t port;
+ struct dstring target;
+};
+
+struct rdata_ds
+{
+ uint16_t key_tag;
+ uint8_t algo;
+ uint8_t digest_type;
+ uint32_t digest_len;
+ uint8_t *digest;
+};
+
+struct rdata_rrsig
+{
+ uint16_t type_covered;
+ uint8_t algo;
+ uint8_t labels;
+ uint32_t original_ttl;
+ uint32_t sig_expiration;
+ uint32_t sig_inception;
+ uint16_t key_tag;
+ uint32_t signature_len;
+ uint8_t *signature;
+ struct dstring signer_name;
+};
+
+struct rdata_nsec
+{
+ uint16_t maps_len;
+ struct dstring next_domain;
+ struct dstring type_bit_maps;
+};
+
+struct rdata_dnskey
+{
+ uint16_t flags;
+ uint8_t protocol;
+ uint8_t algo;
+ uint32_t public_key_len;
+ uint8_t *public_key;
+};
+
+struct rdata_nsec3
+{
+ uint8_t hash_algo;
+ uint8_t flags;
+ uint8_t salt_len;
+ uint8_t hash_len;
+ uint16_t iteration;
+ uint16_t maps_len;
+ uint8_t *salt_value;
+ uint8_t *next_hash_owner;
+ struct dstring type_bit_maps;
+};
+
+struct rdata_nsec3param
+{
+ uint8_t hash_algo;
+ uint8_t flags;
+ uint8_t salt_len;
+ uint16_t iteration;
+ uint8_t *salt_value;
+};
+
+/* rr is short for resource record */
+struct dns_resource_record
+{
+ struct dstring qname;
+ enum dns_rr_type type;
+ uint16_t rr_class;
+ uint32_t ttl; /* 1byte: extended RCODE; 1byte: version; 2bytes: Z(upper bit) if type is OPT */
+ uint16_t rdlength;
+ union
+ {
+
+ struct dstring cname;
+ struct dstring mb;
+ struct dstring md;
+ struct dstring mf;
+ struct dstring mg;
+ struct dstring mr;
+ struct dstring ns;
+ struct dstring ptr;
+ struct dstring a;
+ struct dstring aaaa;
+ struct dstring dname;
+ struct dstring isdn;
+ struct dstring unknown;
+
+ struct dstring txt;
+ struct dstring null;
+
+ struct rdata_hinfo hinfo;
+ struct rdata_minfo minfo;
+ struct rdata_mx mx;
+ struct rdata_soa soa;
+ struct rdata_rp rp;
+ struct rdata_wks wks;
+ struct rdata_srv srv;
+ struct rdata_ds ds;
+ struct rdata_rrsig rrsig;
+ struct rdata_nsec nsec;
+ struct rdata_dnskey dnskey;
+ struct rdata_nsec3 nsec3;
+ struct rdata_nsec3param nsec3param;
+ struct dstring string;
+ } rdata;
+};
+
+struct dns_query_question
+{
+ enum dns_rr_type qtype;
+ uint16_t qclass;
+ size_t qname_sz;
+ uint8_t qname[DNS_NAME_MAX];
+};
diff --git a/src/dns_resource_record_exporter.cpp b/src/dns_resource_record_exporter.cpp
new file mode 100644
index 0000000..7dd5900
--- /dev/null
+++ b/src/dns_resource_record_exporter.cpp
@@ -0,0 +1,230 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "cJSON.h"
+#include "dns_decoder.h"
+#include "dns_resource_record.h"
+
+
+void dns_resource_record_str2hex_append(cJSON *one_rr_object, uint8_t *str, size_t str_sz, const char *key)
+{
+ if(one_rr_object==NULL || str==NULL || str_sz==0 || key==NULL)
+ {
+ return;
+ }
+
+ size_t offset=0;
+ char hex_buff[4096]={0};
+ size_t hex_buff_sz=sizeof(hex_buff);
+ const char hexChars[] = "0123456789abcdef";
+
+ for (size_t i = 0; i < str_sz && i<((hex_buff_sz/2)-2); i++)
+ {
+ hex_buff[offset++]=hexChars[(str[i] >> 4) & 0x0F];
+ hex_buff[offset++]=hexChars[str[i] & 0x0F];
+ }
+
+ if(offset>0)
+ {
+ hex_buff[offset]='\0';
+ cJSON_AddStringToObject(one_rr_object, key, hex_buff);
+ }
+}
+
+void dns_resource_record_dstring_append(cJSON *one_rr_object, struct dstring *dstr, const char *key)
+{
+ if(dstr->value_sz > 0)
+ {
+ cJSON_AddStringToObject(one_rr_object, key, (char *)(dstr->value));
+ }
+}
+
+const char *dns_resource_record_json_exporter(struct dns_resource_record *rr_array, uint16_t n_rr)
+{
+ if(rr_array==NULL || n_rr==0)
+ {
+ return NULL;
+ }
+
+ char ip_str[128];
+ cJSON *dns_rr_array=cJSON_CreateArray();
+
+ for(uint16_t i=0; i<n_rr; i++)
+ {
+ cJSON *one_rr_object=cJSON_CreateObject();
+ struct dns_resource_record *dns_rr=&(rr_array[i]);
+
+ if(dns_rr->type == DNS_RR_TYPE_OPT)
+ {
+ cJSON_AddStringToObject(one_rr_object, "name", (const char *)(dns_rr->qname.value));
+ cJSON_AddNumberToObject(one_rr_object, "type", dns_rr->type);
+ cJSON_AddNumberToObject(one_rr_object, "udp_payload", dns_rr->rr_class);
+ cJSON_AddNumberToObject(one_rr_object, "rcode", (int)(dns_rr->ttl>>24));
+ cJSON_AddNumberToObject(one_rr_object, "version", (int)((dns_rr->ttl>>16)&0xFF));
+ cJSON_AddNumberToObject(one_rr_object, "Z", (int)(dns_rr->ttl&&0xFFFF));
+ cJSON_AddNumberToObject(one_rr_object, "rdlength", dns_rr->rdlength);
+ }
+ else
+ {
+ cJSON_AddStringToObject(one_rr_object, "name", (const char *)(dns_rr->qname.value));
+ cJSON_AddNumberToObject(one_rr_object, "type", dns_rr->type);
+ cJSON_AddNumberToObject(one_rr_object, "class", dns_rr->rr_class);
+ cJSON_AddNumberToObject(one_rr_object, "ttl", dns_rr->ttl);
+ cJSON_AddNumberToObject(one_rr_object, "rdlength", dns_rr->rdlength);
+ }
+
+ if(dns_rr->rdlength==0)
+ {
+ cJSON_AddItemToArray(dns_rr_array, one_rr_object);
+ continue;
+ }
+
+ switch(dns_rr->type)
+ {
+ case DNS_RR_TYPE_A:
+ inet_ntop(AF_INET, (void *)(dns_rr->rdata.a.value), ip_str, sizeof(ip_str));
+ cJSON_AddStringToObject(one_rr_object, "a", ip_str);
+ break;
+ case DNS_RR_TYPE_AAAA:
+ inet_ntop(AF_INET6, dns_rr->rdata.aaaa.value, ip_str, sizeof(ip_str));
+ cJSON_AddStringToObject(one_rr_object, "aaaa", ip_str);
+ break;
+ case DNS_RR_TYPE_NS:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.ns), "ns");
+ break;
+ case DNS_RR_TYPE_MD:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.md), "md");
+ break;
+ case DNS_RR_TYPE_MF:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.mf), "mf");
+ break;
+ case DNS_RR_TYPE_CNAME:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.cname), "cname");
+ break;
+ case DNS_RR_TYPE_MB:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.mb), "mb");
+ break;
+ case DNS_RR_TYPE_MG:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.mg), "mg");
+ break;
+ case DNS_RR_TYPE_MR:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.mr), "mr");
+ break;
+ case DNS_RR_TYPE_TXT:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.txt), "txt");
+ cJSON_AddNumberToObject(one_rr_object, "size", dns_rr->rdata.txt.value_sz);
+ break;
+ case DNS_RR_TYPE_NULL:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.null), "null");
+ cJSON_AddNumberToObject(one_rr_object, "size", dns_rr->rdata.null.value_sz);
+ break;
+ case DNS_RR_TYPE_PTR:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.ptr), "ptr");
+ break;
+ case DNS_RR_TYPE_HINFO:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.hinfo.cpu), "cpu");
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.hinfo.os), "os");
+ break;
+ case DNS_RR_TYPE_MINFO:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.minfo.rmailbx), "rmailbx");
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.minfo.emailbx), "emailbx");
+ break;
+ case DNS_RR_TYPE_MX:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.mx.exchange), "exchange");
+ cJSON_AddNumberToObject(one_rr_object, "preference", dns_rr->rdata.mx.preference);
+ break;
+ case DNS_RR_TYPE_RP:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.rp.mailbox), "mailbox");
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.rp.txt_rr), "txt_rr");
+ break;
+ case DNS_RR_TYPE_SOA:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.soa.mname), "mname");
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.soa.rname), "rname");
+ cJSON_AddNumberToObject(one_rr_object, "serial", dns_rr->rdata.soa.serial);
+ cJSON_AddNumberToObject(one_rr_object, "refresh", dns_rr->rdata.soa.refresh);
+ cJSON_AddNumberToObject(one_rr_object, "retry", dns_rr->rdata.soa.retry);
+ cJSON_AddNumberToObject(one_rr_object, "cname", dns_rr->rdata.soa.expire);
+ cJSON_AddNumberToObject(one_rr_object, "minimum", dns_rr->rdata.soa.minimum);
+ break;
+
+ case DNS_RR_TYPE_WKS:
+ cJSON_AddStringToObject(one_rr_object, "addr", ip_str);
+ cJSON_AddNumberToObject(one_rr_object, "protocol", dns_rr->rdata.wks.protocol);
+ cJSON_AddNumberToObject(one_rr_object, "size", dns_rr->rdata.wks.size);
+
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.wks.bitmap, dns_rr->rdata.wks.size, "bitmap");
+ break;
+ case DNS_RR_TYPE_OPT:
+ break;
+ case DNS_RR_TYPE_DS:
+ cJSON_AddNumberToObject(one_rr_object, "key_tag", dns_rr->rdata.ds.key_tag);
+ cJSON_AddNumberToObject(one_rr_object, "algo", dns_rr->rdata.ds.algo);
+ cJSON_AddNumberToObject(one_rr_object, "digest_type", dns_rr->rdata.ds.digest_type);
+ cJSON_AddNumberToObject(one_rr_object, "digest_len", dns_rr->rdata.ds.digest_len);
+
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.ds.digest, dns_rr->rdata.ds.digest_len, "digest");
+ break;
+ case DNS_RR_TYPE_RRSIG:
+ cJSON_AddNumberToObject(one_rr_object, "type_covered", dns_rr->rdata.rrsig.type_covered);
+ cJSON_AddNumberToObject(one_rr_object, "algo", dns_rr->rdata.rrsig.algo);
+ cJSON_AddNumberToObject(one_rr_object, "labels", dns_rr->rdata.rrsig.labels);
+ cJSON_AddNumberToObject(one_rr_object, "original_ttl", dns_rr->rdata.rrsig.original_ttl);
+ cJSON_AddNumberToObject(one_rr_object, "sig_expiration", dns_rr->rdata.rrsig.sig_expiration);
+ cJSON_AddNumberToObject(one_rr_object, "sig_inception", dns_rr->rdata.rrsig.sig_inception);
+ cJSON_AddNumberToObject(one_rr_object, "key_tag", dns_rr->rdata.rrsig.key_tag);
+
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.rrsig.signer_name), "signer_name");
+
+ cJSON_AddNumberToObject(one_rr_object, "signature_len", dns_rr->rdata.rrsig.signature_len);
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.rrsig.signature, dns_rr->rdata.rrsig.signature_len, "signature");
+ break;
+ case DNS_RR_TYPE_NSEC:
+ dns_resource_record_dstring_append(one_rr_object, &(dns_rr->rdata.nsec.next_domain), "next_domain");
+ cJSON_AddNumberToObject(one_rr_object, "maps_len", dns_rr->rdata.nsec.type_bit_maps.value_sz);
+
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.nsec.type_bit_maps.value, dns_rr->rdata.nsec.type_bit_maps.value_sz, "type_bit_maps");
+ break;
+ case DNS_RR_TYPE_DNSKEY:
+ cJSON_AddNumberToObject(one_rr_object, "flags", dns_rr->rdata.dnskey.flags);
+ cJSON_AddNumberToObject(one_rr_object, "protocol", dns_rr->rdata.dnskey.protocol);
+ cJSON_AddNumberToObject(one_rr_object, "algo", dns_rr->rdata.dnskey.algo);
+ cJSON_AddNumberToObject(one_rr_object, "public_key_len", dns_rr->rdata.dnskey.public_key_len);
+
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.dnskey.public_key, dns_rr->rdata.dnskey.public_key_len, "public_key");
+ break;
+ case DNS_RR_TYPE_NSEC3:
+ cJSON_AddNumberToObject(one_rr_object, "hash_algo", dns_rr->rdata.nsec3.hash_algo);
+ cJSON_AddNumberToObject(one_rr_object, "flags", dns_rr->rdata.nsec3.flags);
+ cJSON_AddNumberToObject(one_rr_object, "iteration", dns_rr->rdata.nsec3.iteration);
+
+ cJSON_AddNumberToObject(one_rr_object, "salt_len", dns_rr->rdata.nsec3.salt_len);
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.nsec3.salt_value, dns_rr->rdata.nsec3.salt_len, "salt_value");
+
+ cJSON_AddNumberToObject(one_rr_object, "hash_len", dns_rr->rdata.nsec3.hash_len);
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.nsec3.next_hash_owner, dns_rr->rdata.nsec3.hash_len, "next_hash_owner");
+
+ cJSON_AddNumberToObject(one_rr_object, "maps_len", dns_rr->rdata.nsec3.type_bit_maps.value_sz);
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.nsec3.type_bit_maps.value,dns_rr->rdata.nsec3.type_bit_maps.value_sz, "type_bit_maps");
+ break;
+ case DNS_RR_TYPE_NSEC3PARAM:
+ cJSON_AddNumberToObject(one_rr_object, "hash_algo", dns_rr->rdata.nsec3param.hash_algo);
+ cJSON_AddNumberToObject(one_rr_object, "flags", dns_rr->rdata.nsec3param.flags);
+ cJSON_AddNumberToObject(one_rr_object, "iteration", dns_rr->rdata.nsec3param.iteration);
+ cJSON_AddNumberToObject(one_rr_object, "salt_len", dns_rr->rdata.nsec3param.salt_len);
+
+ dns_resource_record_str2hex_append(one_rr_object, dns_rr->rdata.nsec3param.salt_value, dns_rr->rdata.nsec3param.salt_len, "salt_value");
+ break;
+ default:
+ break;
+ }
+
+ cJSON_AddItemToArray(dns_rr_array, one_rr_object);
+ }
+
+ char *json_str=cJSON_PrintUnformatted(dns_rr_array);
+ cJSON_Delete(dns_rr_array);
+
+ return json_str;
+} \ No newline at end of file
diff --git a/src/version.map b/src/version.map
index 056069e..dbead6a 100644
--- a/src/version.map
+++ b/src/version.map
@@ -6,10 +6,14 @@ global:
*dns_message_type_get*;
*dns_message_header_id_get*;
*dns_message_header_flag_get0*;
- *dns_message_question_get0*;
+ *dns_message_query_question_get0*;
+ *dns_query_question_qname_get0*;
+ *dns_query_question_qtype_get0*;
+ *dns_query_question_qclass_get0*;
*dns_message_answer_resource_record_get0*;
*dns_message_authority_resource_record_get0*;
*dns_message_additional_resource_record_get0*;
+ *dns_resource_record_json_exporter*;
*dns_message_transaction_index_get*;
*GIT*;
};