diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/dns_decoder.cpp | 195 | ||||
| -rw-r--r-- | src/dns_resource_record.h | 219 | ||||
| -rw-r--r-- | src/dns_resource_record_exporter.cpp | 230 | ||||
| -rw-r--r-- | src/version.map | 6 |
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*; }; |
