#include #include #include #include #include #include #ifdef __cplusplus extern "C" { #include "cJSON.h" #include "dns_decoder.h" #include "toml/toml.h" #include "stellar/stellar.h" #include "stellar/session.h" #include "stellar/session_exdata.h" #include "stellar/session_mq.h" } #endif #define DNS_DECODER_TEST_TOML_PATH "./etc/dns/dns_decoder.toml" struct dns_decoder_test_plugin_env { int plugin_id; int topic_id; int result_index; int commit_result_enable; int write_result_enable; int decode_resource_record_enable; int export_resource_record_enable; }; extern "C" void perf_resource_record_decode(struct dns_message *dns_msg); extern "C" int commit_test_result_json(cJSON *node, const char *name); void dns_real_result_write_file(char *result_str) { FILE *fp=fopen("dns_real_result.json", "a+"); if(fp!=NULL) { fwrite(result_str, 1, strlen(result_str), fp); fclose(fp); } } void dns_decoder_test_message_cb(struct session *ss, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env_str) { struct dns_message *dns_msg=(struct dns_message *)msg; enum dns_message_type type=dns_message_type_get(dns_msg); if(type==DNS_MESSAGE_TRANSACTION_BEGIN || type==DNS_MESSAGE_TRANSACTION_END) { return; } //uint16_t id=dns_message_header_id_get(dns_msg); struct dns_decoder_test_plugin_env *plugin_env=(struct dns_decoder_test_plugin_env *)plugin_env_str; if(plugin_env->decode_resource_record_enable==1) { perf_resource_record_decode(dns_msg); return ; } cJSON *real_result=cJSON_CreateObject(); cJSON_AddStringToObject(real_result, "Tuple4", session_get0_readable_addr(ss)); uint16_t n_question=0; struct dns_query_question *question=NULL; dns_message_query_question_get0(dns_msg, &question, &n_question); if(n_question>0 && question!=NULL) { cJSON_AddStringToObject(real_result, "dns_qname", dns_query_question_qname_get0(question)); cJSON_AddNumberToObject(real_result, "dns_qtype", dns_query_question_qtype_get0(question)); cJSON_AddNumberToObject(real_result, "dns_qclass", dns_query_question_qclass_get0(question)); } struct dns_flag *flag=dns_message_header_flag_get0(dns_msg); if(flag!=NULL) { cJSON_AddNumberToObject(real_result, "dns_qr", (double)(flag->qr)); cJSON_AddNumberToObject(real_result, "dns_opcode", (double)(flag->opcode)); cJSON_AddNumberToObject(real_result, "dns_rd", (double)(flag->rd)); } uint16_t n_answer_rr=0; struct dns_resource_record *answer_rr=NULL; dns_message_answer_resource_record_get0(dns_msg, &answer_rr, &n_answer_rr); uint16_t n_authority_rr=0; struct dns_resource_record *authority_rr=NULL; dns_message_authority_resource_record_get0(dns_msg, &authority_rr, &n_authority_rr); uint16_t n_additional_rr=0; struct dns_resource_record *additional_rr=NULL; dns_message_additional_resource_record_get0(dns_msg, &additional_rr, &n_additional_rr); const char *answer=dns_resource_record_json_exporter(answer_rr, n_answer_rr); const char *authority=dns_resource_record_json_exporter(authority_rr, n_authority_rr); const char *additional=dns_resource_record_json_exporter(additional_rr, n_additional_rr); cJSON *rr_array=cJSON_CreateObject(); if(answer!=NULL) { cJSON *rr_object=cJSON_Parse(answer); cJSON_AddItemToObject(rr_array, "answer", rr_object); free((void *)answer); } if(authority!=NULL) { cJSON *rr_object=cJSON_Parse(authority); cJSON_AddItemToObject(rr_array, "authority", rr_object); free((void *)authority); } if(additional!=NULL) { cJSON *rr_object=cJSON_Parse(additional); cJSON_AddItemToObject(rr_array, "additional", rr_object); free((void *)additional); } cJSON_AddItemToObject(real_result, "rr", rr_array); if(plugin_env->write_result_enable==1) { char *real_result_str=cJSON_Print(real_result); dns_real_result_write_file(real_result_str); free(real_result_str); } if(plugin_env->commit_result_enable==1) { char result_name[16]=""; sprintf(result_name, "DNS_RESULT_%d", plugin_env->result_index++); commit_test_result_json(real_result, result_name); } else { cJSON_Delete(real_result); } } void *dns_decoder_test_per_session_context_new(struct session *sess, void *plugin_env) { return NULL; } void dns_decoder_test_per_session_context_free(struct session *sess, void *session_ctx, void *plugin_env) { } int32_t dns_decoder_test_config_load(const char *cfg_path, struct dns_decoder_test_plugin_env *plugin_env) { FILE *fp=fopen(cfg_path, "r"); if (NULL==fp) { fprintf(stderr, "[%s:%d] Can't open config file: %s", __FUNCTION__, __LINE__, cfg_path); return -1; } int32_t ret=0; char errbuf[256]={0}; toml_table_t *root=toml_parse_file(fp, errbuf, sizeof(errbuf)); fclose(fp); toml_table_t *decoder_tbl=toml_table_in(root, "decoder"); if(NULL==decoder_tbl) { fprintf(stderr, "[%s:%d] config file: %s has no key: [decoder]", __FUNCTION__, __LINE__, cfg_path); toml_free(root); return -1; } toml_table_t *dns_tbl=toml_table_in(decoder_tbl, "dns"); if(NULL==dns_tbl) { fprintf(stderr, "[%s:%d] config file: %s has no key: [decoder.dns]", __FUNCTION__, __LINE__, cfg_path); toml_free(root); return -1; } toml_table_t *test_tbl=toml_table_in(dns_tbl, "test"); if(NULL==test_tbl) { fprintf(stderr, "[%s:%d] config file: %s has no key: [decoder.dns.test]", __FUNCTION__, __LINE__, cfg_path); toml_free(root); return -1; } toml_datum_t commit_result_enable_val=toml_string_in(test_tbl, "commit_result_enable"); if(commit_result_enable_val.ok==0) { plugin_env->commit_result_enable=0; fprintf(stderr, "[%s:%d] config file: %s has no key: [decoder.dns.test.commit_result_enable]", __FUNCTION__, __LINE__, cfg_path); } else { if(memcmp("no", commit_result_enable_val.u.s, strlen("no"))==0) { plugin_env->commit_result_enable=0; } else if(memcmp("yes", commit_result_enable_val.u.s, strlen("yes"))==0) { plugin_env->commit_result_enable=1; } else { plugin_env->commit_result_enable=1; fprintf(stderr, "[%s:%d] config file: %s key: [decoder.dns.test.commit_result_enable] value is not yes or no", __FUNCTION__, __LINE__, cfg_path); } } toml_datum_t write_result_enable_val=toml_string_in(test_tbl, "write_result_enable"); if(write_result_enable_val.ok==0) { plugin_env->write_result_enable=0; fprintf(stderr, "[%s:%d] config file: %s has no key: [decoder.dns.test.write_result_enable]", __FUNCTION__, __LINE__, cfg_path); } else { if(memcmp("no", write_result_enable_val.u.s, strlen("no"))==0) { plugin_env->write_result_enable=0; } else if(memcmp("yes", write_result_enable_val.u.s, strlen("yes"))==0) { plugin_env->write_result_enable=1; } else { plugin_env->write_result_enable=1; fprintf(stderr, "[%s:%d] config file: %s key: [decoder.dns.test.write_result_enable] value is not yes or no", __FUNCTION__, __LINE__, cfg_path); } } // decode_resource_record_enable toml_datum_t decode_resource_record_enable_val=toml_string_in(test_tbl, "decode_resource_record_enable"); if(decode_resource_record_enable_val.ok==0) { plugin_env->decode_resource_record_enable=0; fprintf(stderr, "[%s:%d] config file: %s has no key: [decoder.dns.test.decode_resource_record_enable]", __FUNCTION__, __LINE__, cfg_path); } else { if(memcmp("no", decode_resource_record_enable_val.u.s, strlen("no"))==0) { plugin_env->decode_resource_record_enable=0; } else if(memcmp("yes", decode_resource_record_enable_val.u.s, strlen("yes"))==0) { plugin_env->decode_resource_record_enable=1; } else { plugin_env->decode_resource_record_enable=1; fprintf(stderr, "[%s:%d] config file: %s key: [decoder.dns.test.decode_resource_record_enable] value is not yes or no", __FUNCTION__, __LINE__, cfg_path); } } // export_resource_record_enable toml_datum_t export_resource_record_enable_val=toml_string_in(test_tbl, "export_resource_record_enable"); if(export_resource_record_enable_val.ok==0) { plugin_env->export_resource_record_enable=0; fprintf(stderr, "[%s:%d] config file: %s has no key: [decoder.dns.test.export_resource_record_enable]", __FUNCTION__, __LINE__, cfg_path); } else { if(memcmp("no", export_resource_record_enable_val.u.s, strlen("no"))==0) { plugin_env->export_resource_record_enable=0; } else if(memcmp("yes", export_resource_record_enable_val.u.s, strlen("yes"))==0) { plugin_env->export_resource_record_enable=1; } else { plugin_env->export_resource_record_enable=1; fprintf(stderr, "[%s:%d] config file: %s key: [decoder.dns.test.export_resource_record_enable] value is not yes or no", __FUNCTION__, __LINE__, cfg_path); } } toml_free(root); return ret; } extern "C" void *dns_decoder_test_init(struct stellar *st) { struct dns_decoder_test_plugin_env *plugin_env=(struct dns_decoder_test_plugin_env *)calloc(1, sizeof(struct dns_decoder_test_plugin_env)); plugin_env->result_index=1; dns_decoder_test_config_load(DNS_DECODER_TEST_TOML_PATH, plugin_env); plugin_env->plugin_id=stellar_session_plugin_register(st, dns_decoder_test_per_session_context_new, dns_decoder_test_per_session_context_free, plugin_env); if(plugin_env->plugin_id<0) { printf("dns_decoder_test_init: stellar_plugin_register failed !!!\n"); exit(-1); } plugin_env->topic_id=stellar_session_mq_get_topic_id(st, DNS_MESSAGE_TOPIC); if(plugin_env->topic_id<0) { printf("stellar_session_mq_get_topic_id failed, topic: %s \n", DNS_MESSAGE_TOPIC); exit(-1); } stellar_session_mq_subscribe(st, plugin_env->topic_id, dns_decoder_test_message_cb, plugin_env->plugin_id); return (void *)plugin_env; } extern "C" void dns_decoder_test_exit(void *plugin_env_str) { if(plugin_env_str!=NULL) { free(plugin_env_str); } }