diff options
| author | liuxueli <[email protected]> | 2019-04-19 13:16:19 +0800 |
|---|---|---|
| committer | liuxueli <[email protected]> | 2019-04-19 13:16:19 +0800 |
| commit | e4eb288e695a9d3ecf199454e16030755b4d9e1d (patch) | |
| tree | 9437045f6cdd8306b14b0d74ac61150bd6a0aa1c | |
create version
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | bin/dns.conf | 18 | ||||
| -rw-r--r-- | bin/dns.inf | 16 | ||||
| -rw-r--r-- | readme.txt | 69 | ||||
| -rw-r--r-- | src/Makefile | 27 | ||||
| -rw-r--r-- | src/dns.cpp | 1916 | ||||
| -rw-r--r-- | src/dns.h | 343 | ||||
| -rw-r--r-- | src/dns_global.map | 11 | ||||
| -rw-r--r-- | src/dns_internal.h | 177 | ||||
| -rw-r--r-- | test/bin/dns_test.inf | 9 | ||||
| -rw-r--r-- | test/src/Makefile | 5 | ||||
| -rw-r--r-- | test/src/dns_test.c | 365 |
12 files changed, 2960 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1d7b460 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: + cd ./src/;make; +clean: + cd ./src/;make clean; diff --git a/bin/dns.conf b/bin/dns.conf new file mode 100644 index 0000000..8a17f80 --- /dev/null +++ b/bin/dns.conf @@ -0,0 +1,18 @@ +[DNS] +STAT_CYCLE=2 +LOG_LEVEL=30 +LOG_PATH=./log/dns/dns + +[REGISATER_INFO] +1 DNS_ALL +2 DNS_REQ_ALL +3 DNS_RES_ALL +4 DNS_REQ_HDR +5 DNS_RES_HDR +6 DNS_RES_QUERY +7 DNS_RES_RRS +8 DNS_RES_ANSWER +9 DNS_RES_AUTH +10 DNS_RES_ADD + + diff --git a/bin/dns.inf b/bin/dns.inf new file mode 100644 index 0000000..ee8d225 --- /dev/null +++ b/bin/dns.inf @@ -0,0 +1,16 @@ +[PLUGINFO] +PLUGNAME=DNS +SO_PATH=./plug/protocol/dns/dns.so +INIT_FUNC=DNS_INIT +DESTROY_FUNC=DNS_DESTROY +FLAGCHANGE_FUNC=FLAG_CHANGE +FLAGSTATE_FUNC=PROT_FUNSTAT +GETPLUGID_FUNC=GET_PLUGID + +[UDP] +FUNC_FLAG=ALL +FUNC_NAME=DNS_UDP_ENTRY + +[TCP] +FUNC_FLAG=ALL +FUNC_NAME=DNS_TCP_ENTRY diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..882b63b --- /dev/null +++ b/readme.txt @@ -0,0 +1,69 @@ +/* + *Author ljp + *V1.01 2015-01-05 ��ͷ�ļ����������µ�stream.h + *V1.02 2015-01-16 ��dns_compress_domain����whileѭ����������\0��Ϊ\n + * ���Ӷ�TCP DNS��ѯ��֧�� + *V1.03 2015-01-26 cheat pkt TTL set 0.5->1hour + *V1.04 2015-02-05 ��DNS�������ݰ�BUG + *V1.05 2015-02-12 build_dns_payload�����Ӷ�AAAA����Ӧ���֧�� + *V1.06 2015-03-05 ������TCP DNSʱparse_dns��msg��ֵСBUG + *V1.07 2015-03-16 ��A/AAAAӦ���������ϢBUG + *V1.08 2015-05-07 ��au/adӦ���������ϢBUG + *V1.09 2015-07-15 ��qtype��qclass��������δת������������� + + -------------------------------------------------------------------------- + *2015-09-07, LiJia, ��ע���ȡflag_id BUG. + *2015-09-29, LiJia, ��TCPЭ��, û�����������ֶ�BUG. + *2015-10-10, LiJia, ��FLAG_CHANGE()����û��copy�ַ������EOF��BUG. +*/ + +liuxueli�� + +20160920 +1��������Ӧ������NSEC3��BUG��type_bit_maps�е����⡣ +20160921 +1����������������ʱ��BUG���������쳣���������������һ���ַ���һ��"."��Ŀǰ�ǽ��쳣�������������� +20160922 +1���������ṩƴ�����е���Դ��¼�ĺ��� +2����TXTӦ�����͵�BUG���ڽ�TXT��ָ���Ϊ����(���Ϊ256)�����һ���ַ�Ϊ'\0' +3����nullӦ�����͵�BUG���ڽ�null��ָ���Ϊ����(���Ϊ256)�����һ���ַ�Ϊ'\0' +4����AAAA�е����͵�BUG���ڽ����㿽��������û���ԡ�\0����β����ת�ַ�����ʱ��ת�IJ���ȷ +5�����Ӷ�NSEC3PARAMӦ������֧�� +20160923 +1����NSECӦ�����͵�BUG��next_domain_name��ʾ�ַ�������ʮ������ +2����NSEC3Ӧ�����͵�BUG��salt_value��ʾ��ʮ�����ƣ������ַ��� +3�����������Ƕ��ѹ����BUG +20160927 +1��������ԭʼ����BUG�����ݼѸ�Ļ�ȡԭʼ���ĺ������ж��䷵��ֵ��0����ԭʼ����1��IP��Ƭ�������ص������� +20160928 +1������DNSЭ���ͳ����Ϣ +2�����жϴ�����������DNS�е�FLAG_Z��־λ������0����һ���Ǵ��� +20160929 +1�����п���Խ��ĵط����ϳ������� +20160930-20161008 +1������DNS������������ļ� +2������7.2����ϵͳ�ϱ���warning +20161013 +1������Դ��¼�ķָ�����ȥ����\n�� +2��ɾ�����������еı���ԭʼ���ĺ��� +20161018 +1��ɾ���������ô��� +2��������ѹ�������IJ��� +20161117 +1���Ľ����ķ���ֵ��ʼ�շ���APP_STATE_GIVEME��DNS UDP��Ҳ�������ĸ����ֹͬһ��Ԫ�鷢����DNS��ѯ������APP_STATE_GIVEME���Խ��ж����ƭ������ֻ����ƭ��һ�β�ѯ +2���Ļص�ҵ����SESSION_STATE_PENDING��SESSION_STATE_DATA��SESSION_STATE_CLOSE״̬ +3������pme�ռ䣬1����������ҵ����pme��2��û��pme�ռ䣬SESSION_STATE_CLOSE״̬�ص�����ҵ��� +20161121 +1��ɾ��������Ϣ +2����memset�IJ�����sizeofʹ�ýṹ�壬�������ñ��� +3����Խ���BUG������DNS_TYPE_NSEC3Ӧ������ʱ����ȡsalt_len��hash_lenʱ��Ҫ��ptrת��Ϊ(unsigned char *) +20161123 +1���鿴���룬���ڴ�����Խ��ĵط� +20161129 +1������ڴ�й¶���� +20171103 +1��ͬ�����ߴ��� +20180615 +1��������NSEC3Ӧ����������� +2����DNS_TCP����ʧ�����⣬��ֻ����pending״̬ʱ��ȥ2�ֽ�DNS������ +3���İ汾��
\ No newline at end of file diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..889f178 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,27 @@ +CC = gcc +CCC = g++ +CFLAGS = -Wall -g -fPIC +INC = -I./include/ +LDFLAGS = -L./lib/ +LIBS = -lMESA_handle_logger -lMESA_prof_load -lMESA_field_stat2 +OBJ = dns.o +TARGET = dns.so + +.c.o: + $(CC) -c $(CFLAGS) $< $(INC) +.cpp.o: + $(CCC) -c $(CFLAGS) $(INC) $< + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(CCC) -o $@ $(OBJ) $(LDFLAGS) $(LIBS) -shared + cp $(TARGET) ../bin/ + +CP: + cp $(TARGET) ../bin/ + +clean: + -rm -rf $(OBJ) $(TARGET) + +.PHONY:clean diff --git a/src/dns.cpp b/src/dns.cpp new file mode 100644 index 0000000..c95bb8c --- /dev/null +++ b/src/dns.cpp @@ -0,0 +1,1916 @@ +/* + *Author ljp + *V1.01 2015-01-05 ��ͷ�ļ����������µ�stream.h + *V1.02 2015-01-16 ��dns_compress_domain����whileѭ����������\0��Ϊ\n + * ���Ӷ�TCP DNS��ѯ��֧�� + *V1.03 2015-01-26 cheat pkt TTL set 0.5->1hour + *V1.04 2015-02-05 ��DNS�������ݰ�BUG + *V1.05 2015-02-12 build_dns_payload�����Ӷ�AAAA����Ӧ���֧�� + *V1.06 2015-03-05 ������TCP DNSʱparse_dns��msg��ֵСBUG + *V1.07 2015-03-16 ��A/AAAAӦ���������ϢBUG + *V1.08 2015-05-07 ��au/adӦ���������ϢBUG + *V1.09 2015-07-15 ��qtype��qclass��������δת������������� + + -------------------------------------------------------------------------- + *2015-09-07, LiJia, ��ע���ȡflag_id BUG. + *2015-09-29, LiJia, ��TCPЭ��, û�����������ֶ�BUG. + *2015-10-10, LiJia, ��FLAG_CHANGE()����û��copy�ַ������EOF��BUG. + *2016-09-03, liuxueli, �Ĵ����ʽ +*/ +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> +#include <pthread.h> +#include <assert.h> +#include <sys/time.h> +#include <MESA/stream.h> +#include <MESA/field_stat2.h> +#include <MESA/MESA_prof_load.h> +#include <MESA/MESA_handle_logger.h> +#include "dns.h" +#include "dns_internal.h" + +int DNS_PROTOCOL_VERSION_20190417; +unsigned long long dns_register_flag = 0; +unsigned short dns_plugid = 0; +static pthread_mutex_t dns_lock; +int dns_register_flag_num = 0; +int pcap_index = 0; + +const char *dns_conf_file = "./conf/dns/dns.conf"; +g_dns_proto_info_t g_dns_proto_info; + +static dns_str_contrast_id_t DNS_FLAG_ID[] = +{ + {"DNS_ALL", DNS_ALL}, + {"DNS_REQ_ALL", DNS_REQ_ALL}, + {"DNS_RES_ALL", DNS_RES_ALL}, + {"DNS_REQ_HDR", DNS_REQ_HDR}, + {"DNS_RES_HDR", DNS_RES_HDR}, + {"DNS_RES_QUERY", DNS_RES_QUERY}, + {"DNS_RES_RRS", DNS_RES_RRS}, + {"DNS_RES_ANSWER", DNS_RES_ANSWER}, + {"DNS_RES_AUTH", DNS_RES_AUTH}, + {"DNS_RES_ADD", DNS_RES_ADD} +}; + +static dns_str_contrast_id_t DNS_STATIS_INFO[] = +{ + {"V4_T_PPS", V4_T_PPS}, + {"V4_T_BPS", V4_T_BPS}, + {"V4_U_PPS", V4_U_PPS}, + {"V4_U_BPS", V4_U_BPS}, + {"V6_T_PPS", V6_T_PPS}, + {"V6_T_BPS", V6_T_BPS}, + {"V6_U_PPS", V6_U_PPS}, + {"V6_U_BPS", V6_U_BPS}, + {"PKT_UNKNOWN", PKT_UNKNOWN}, + {"Q_PKT", Q_PKT}, + {"R_PKT", R_PKT}, + {"ERR_PKT", ERR_PKT}, + {"Q_A", Q_A}, + {"Q_AAAA", Q_AAAA}, + {"Q_CNAME", Q_CNAME}, + {"Q_UNKNOWN", Q_UNKNOWN} +}; + + +const unsigned char PCAP_FILE_HEAD[24] = {0xD4, 0xC3, 0xB2, 0xA1, 0x02, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; + + +int get_rr_content2buf(dns_rr_t *rr, int rr_count, char *rr_buf, int buflen, int *dns_sec) +{ + int i = 0, j = 0; + int len = 0, used_len = 0; + char ip_str[128]; + char tmp_buf[2048]; + char maps[2048]; + char salt_value[2048]; + char *buf = NULL; + FILE *fp = NULL; + dns_rr_t *dns_rr = NULL; + + buf = (char *)calloc(1, buflen+1024); + + for(i = 0; i < rr_count; i++) + { + len = 0; + dns_rr = &rr[i]; + + if(dns_rr->type == DNS_TYPE_OPT) + { + used_len += snprintf(buf+used_len, buflen-used_len, + "{RRS%d OPT <name: %s, type: %u, udp_payload: %u, extended RCODE: %u, version: %u, Z; 0X%x, rdlength: %u>};", + i, + dns_rr->name, + dns_rr->type, + dns_rr->rr_class, + dns_rr->ttl >> 24, + (dns_rr->ttl>>16)&0xFF, + dns_rr->ttl&0xFFFF, + dns_rr->rdlength); + } + else + { + used_len += snprintf(buf+used_len, buflen-used_len, "{RRS%d <name: %s, type: %u, rr_class: %u, ttl: %u, rdlength: %u>", + i, + dns_rr->name, + dns_rr->type, + dns_rr->rr_class, + dns_rr->ttl, + dns_rr->rdlength); + + } + + if(dns_rr->rdlength == 0) + { + continue; + } + + switch(dns_rr->type) + { + case DNS_TYPE_A: + inet_ntop(AF_INET, (void *)(dns_rr->rdata.a), ip_str, sizeof(ip_str)); + used_len += snprintf(buf+used_len, buflen-used_len, "[A: %s]};", ip_str); + break; + case DNS_TYPE_NS: + used_len += snprintf(buf+used_len, buflen-used_len, "[NS: %s]};", dns_rr->rdata.ns); + break; + case DNS_TYPE_MD: + used_len += snprintf(buf+used_len, buflen-used_len, "[MD: %s]};", dns_rr->rdata.md); + break; + case DNS_TYPE_MF: + used_len += snprintf(buf+used_len, buflen-used_len, "[MF: %s]};", dns_rr->rdata.mf); + break; + case DNS_TYPE_CNAME: + used_len += snprintf(buf+used_len, buflen-used_len, "[CNAME: %s]};", dns_rr->rdata.cname); + break; + case DNS_TYPE_SOA: + used_len += snprintf(buf+used_len, buflen-used_len, + "[SOA mname: %s, rname: %s, serial: %u, refresh: %u, retry: %u, expire: %u, minimum: %u]};", + dns_rr->rdata.soa->mname, + dns_rr->rdata.soa->rname, + dns_rr->rdata.soa->serial, + dns_rr->rdata.soa->refresh, + dns_rr->rdata.soa->retry, + dns_rr->rdata.soa->expire, + dns_rr->rdata.soa->minimum); + break; + case DNS_TYPE_MB: + used_len += snprintf(buf+used_len, buflen-used_len, "[MB: %s]};", dns_rr->rdata.mb); + break; + case DNS_TYPE_MG: + used_len += snprintf(buf+used_len, buflen-used_len, "[MG: %s]};", dns_rr->rdata.mg); + break; + case DNS_TYPE_MR: + used_len += snprintf(buf+used_len, buflen-used_len, "[MR: %s]};", dns_rr->rdata.mr); + break; + case DNS_TYPE_NULL: + used_len += snprintf(buf+used_len, buflen-used_len, "[null size: %u, null: %s]};", + dns_rr->rdata.null->size, dns_rr->rdata.null->null); + break; + case DNS_TYPE_WKS: + inet_ntop(AF_INET, &(dns_rr->rdata.wks->addr), ip_str, sizeof(ip_str)); + used_len += snprintf(buf+used_len, buflen-used_len, "[WKS addr: %s, protocol: %u, bitmap: %s, size: %u]};", + ip_str, dns_rr->rdata.wks->protocol, dns_rr->rdata.wks->bitmap, dns_rr->rdata.wks->size); + break; + case DNS_TYPE_PTR: + used_len += snprintf(buf+used_len, buflen-used_len, "[PTR: %s]};", dns_rr->rdata.ptr); + break; + case DNS_TYPE_HINFO: + used_len += snprintf(buf+used_len, buflen-used_len, "[HINFO cpu: %s, os: %s]};", + dns_rr->rdata.hinfo->cpu, dns_rr->rdata.hinfo->os); + break; + case DNS_TYPE_MINFO: + used_len += snprintf(buf+used_len, buflen-used_len, "[MINFO rmailbx: %s, emailbx: %s]};", + dns_rr->rdata.minfo->rmailbx, dns_rr->rdata.minfo->emailbx); + break; + case DNS_TYPE_MX: + used_len += snprintf(buf+used_len, buflen-used_len, "[MX preference: %u, exchange: %s]};", + dns_rr->rdata.mx->preference, dns_rr->rdata.mx->exchange); + break; + case DNS_TYPE_TXT: + used_len += snprintf(buf+used_len, buflen-used_len, "[TXT size: %u, txt: %s]};", + dns_rr->rdata.txt->size, dns_rr->rdata.txt->txt); + break; + case DNS_TYPE_AAAA: + if(dns_rr->rdata.aaaa != NULL) + { + inet_ntop(AF_INET6, dns_rr->rdata.aaaa, ip_str, sizeof(ip_str)); + used_len += snprintf(buf+used_len, buflen-used_len, "[AAAA: %s]};", ip_str); + } + break; + case DNS_TYPE_OPT: + break; + case DNS_TYPE_DS: + *dns_sec = 2; + len = 0; + assert(dns_rr->rdata.ds->digest_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.ds->digest_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.ds->digest[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, + "[DS key_tag: %u, algo: %u, digest_type: %u, digest: %s]};", + dns_rr->rdata.ds->key_tag, dns_rr->rdata.ds->algo, + dns_rr->rdata.ds->digest_type, tmp_buf); + break; + case DNS_TYPE_RRSIG: + *dns_sec = 2; + len = 0; + assert(dns_rr->rdata.rrsig->signature_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.rrsig->signature_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.rrsig->signature[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, + "[RRSIG type_covered: %u, algo: %u, labels: %u, original_ttl: %u, sig_expiration: %u, sig_inception: %u, key_tag: %u, signer_name: %s, signature: %s]};", + dns_rr->rdata.rrsig->type_covered, dns_rr->rdata.rrsig->algo, + dns_rr->rdata.rrsig->labels, dns_rr->rdata.rrsig->original_ttl, + dns_rr->rdata.rrsig->sig_expiration, dns_rr->rdata.rrsig->sig_inception, + dns_rr->rdata.rrsig->key_tag, dns_rr->rdata.rrsig->signer_name, tmp_buf); + break; + case DNS_TYPE_NSEC: + *dns_sec = 2; + len = 0; + for(j = 0; j < (int)(dns_rr->rdata.nsec->maps_len); j++) + { + len += snprintf(maps+len, sizeof(maps)-len, "%02x", dns_rr->rdata.nsec->type_bit_maps[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, "[NSEC next_domain: %s, type_bit_maps: %s]};", dns_rr->rdata.nsec->next_domain, maps); + break; + case DNS_TYPE_DNSKEY: + *dns_sec = 2; + len = 0; + assert(dns_rr->rdata.dnskey->public_key_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.dnskey->public_key_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.dnskey->public_key[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, "[DNSKEY flags: %u, protocol: %u, algo: %u, public_key: %s]};", + dns_rr->rdata.dnskey->flags, dns_rr->rdata.dnskey->protocol, dns_rr->rdata.dnskey->algo, tmp_buf); + break; + case DNS_TYPE_NSEC3: + *dns_sec = 2; + memset(tmp_buf, 0, sizeof(tmp_buf)); + memset(maps, 0, sizeof(maps)); + len = 0; + assert(dns_rr->rdata.nsec3->hash_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.nsec3->hash_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.nsec3->next_hash_owner[j]); + } + len = 0; + for(j = 0; j < (int)(dns_rr->rdata.nsec3->maps_len); j++) + { + len += snprintf(maps+len, sizeof(maps)-len, "%02x", dns_rr->rdata.nsec3->type_bit_maps[j]); + } + len = 0; + for(j = 0; j < (int)(dns_rr->rdata.nsec3->salt_len); j++) + { + len += snprintf(salt_value+len, sizeof(salt_value)-len, "%02x", dns_rr->rdata.nsec3->salt_value[j]); + } + + used_len += snprintf(buf+used_len, buflen-used_len, + "[NSEC3 hash_algo: %u, flags: %u, iteration: %u, salt_len: %u, hash_len: %u, salt_value: %s, next_hash_owner: %s, type_bit_maps: %s]};", + dns_rr->rdata.nsec3->hash_algo, dns_rr->rdata.nsec3->flags, + dns_rr->rdata.nsec3->iteration, dns_rr->rdata.nsec3->salt_len, + dns_rr->rdata.nsec3->hash_len, salt_value, tmp_buf, maps); + break; + case DNS_TYPE_NSEC3PARAM: + len = 0; + assert(dns_rr->rdata.nsec3param->salt_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.nsec3param->salt_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.nsec3param->salt_value[j]); + } + + used_len += snprintf(buf+used_len, buflen-used_len, + "[NSEC3PARAM hash_algo: %u, flags: %u, iteration: %u, salt_len: %u, salt_value: %s]};", + dns_rr->rdata.nsec3param->hash_algo, dns_rr->rdata.nsec3param->flags, + dns_rr->rdata.nsec3param->iteration, dns_rr->rdata.nsec3param->salt_len, + tmp_buf); + break; + case DNS_QTYPE_AXFR: + continue; + break; + case DNS_QTYPE_MAILB: + continue; + break; + case DNS_QTYPE_MAILA: + continue; + break; + case DNS_QTYPE_ANY: + continue; + break; + default: + continue; + break; + } + + if(used_len > buflen-1) + break; + + } + if(used_len > buflen-1) + { + memcpy(rr_buf, buf, buflen); + rr_buf[buflen-1] = '\0'; + used_len = buflen; + } + else + { + memcpy(rr_buf, buf, used_len); + rr_buf[used_len] = '\0'; + } + + if(g_dns_proto_info.log_level < 30) + { + fp = fopen("aaaaa", "a+"); + if(fp) + { + fwrite(rr_buf, used_len, 1, fp); + fclose(fp); + fp = NULL; + } + } + + free(buf); + buf = NULL; + + return used_len; +} + +int dns_save_raw_pkt(char *buf, int buflen, const struct streaminfo * a_stream) +{ + int min_len = 0, ret = 0; + void *p_eth_rawpkt = NULL; + int eth_rawpkt_len = 0; + struct timeval t; + pcap_hdr_t pcap_hdr; + int used_len = 0; + raw_ipfrag_list_t *raw_ipfrag = NULL, *p = NULL;; + + memcpy(buf, PCAP_FILE_HEAD, sizeof(PCAP_FILE_HEAD)); + used_len += sizeof(PCAP_FILE_HEAD); + + gettimeofday(&t, NULL); + ret = get_rawpkt_opt_from_streaminfo(a_stream, RAW_PKT_GET_DATA, &p_eth_rawpkt); + switch(ret) + { + case 0: + get_rawpkt_opt_from_streaminfo(a_stream, RAW_PKT_GET_TOT_LEN, ð_rawpkt_len); + + pcap_hdr.tv_sec = t.tv_sec; + pcap_hdr.tv_usec = t.tv_usec; + pcap_hdr.caplen = eth_rawpkt_len; + pcap_hdr.len = pcap_hdr.caplen; + + memcpy(buf+used_len, &pcap_hdr, sizeof(pcap_hdr)); + used_len += sizeof(pcap_hdr); + + if(eth_rawpkt_len <= 0 || p_eth_rawpkt == NULL) + { + return used_len; + } + + min_len = MIN(eth_rawpkt_len, buflen-used_len); + + memcpy(buf+used_len, p_eth_rawpkt, min_len); + used_len += min_len; + break; + case 1: + raw_ipfrag = (raw_ipfrag_list_t *)p_eth_rawpkt; + p = raw_ipfrag; + while(p) + { + if(buflen < used_len+p->pkt_len+(int)sizeof(pcap_hdr)) + { + assert(0); + break; + } + + pcap_hdr.tv_sec = t.tv_sec; + pcap_hdr.tv_usec = t.tv_usec; + pcap_hdr.caplen = eth_rawpkt_len; + pcap_hdr.len = pcap_hdr.caplen; + + memcpy(buf+used_len, &pcap_hdr, sizeof(pcap_hdr)); + used_len += sizeof(pcap_hdr); + + memcpy(buf+used_len, p->frag_packet, p->pkt_len); + used_len += p->pkt_len; + } + break; + default: + return 0; + break; + } + + return used_len; +} + + +int dns_save_error_pkt(const struct streaminfo * a_stream, int error_type) +{ + char buf[8*1024]; + char filename[128]; + int buflen = 8*1024; + int used_len = 0; + FILE *fp = NULL; + + switch(error_type) + { + case DNS_ERROR_QUESTION: + return 0; + break; + case DNS_ERROR_UNKNOWN: + return 0; + break; + case DNS_ERROR_CLASS_UNKNOWN: + return 0; + break; + case DNS_ERROR_PAYLOAD_SHORT: + return 0; + break; + case DNS_ERROR_RR: + return 0; + break; + case DNS_ERROR_ALL: + break; + default: + return 0; + break; + } + used_len = dns_save_raw_pkt(buf, buflen, a_stream); + snprintf(filename, sizeof(filename), "./log/dns/%s_%ld.pcap", printaddr(&a_stream->addr, a_stream->threadnum), random()); + snprintf(filename, sizeof(filename), "/dev/shm/pkt_dump/111_%d_%d.pcap", a_stream->threadnum, pcap_index); + + fp = fopen(filename, "w+"); + if(fp != NULL) + { + fwrite(buf, used_len, 1, fp); + fclose(fp); + fp = NULL; + } + + return 0; +} + +int dns_compress_rr_str(unsigned char *domain, int domain_len, u_char *result) +{ + int section_len = 0; + int result_pos = 1; + int domain_pos = 0; + + if(domain_len < 0 || domain_len > DNS_MAX_NAME+1 || + '.' == domain[0] || '.' == domain[domain_len - 1]) + { + return -1; + } + + while((domain[domain_pos] != '\n')||(domain[domain_pos] != '\0')) + { + section_len = 0; + while((domain[domain_pos] != '.') &&(domain[domain_pos] != '\n')&&(domain[domain_pos] != '\0')) + { + result[result_pos] = domain[domain_pos]; + result_pos++; + domain_pos++; + section_len++; + } + result[result_pos - section_len -1] = section_len; + + if((domain[domain_pos] == '\n')||(domain[domain_pos] == '\0')) + break; + result_pos++; + domain_pos++; + } + + result[result_pos]= '\0'; + + if(result_pos >= domain_len) + { + return result_pos+1; + } + else + { + return result_pos; + } + + return 0; +} + + +int set_cheat_pkt_question(unsigned char *payload, int payload_len, dns_query_question_t *query, int query_num) +{ + unsigned short tqtype = 0; + unsigned short tqclass = 0; + int compress_len = 0, used_len = 0; + u_char compress_name[DNS_MAX_NAME+1]; + + /* ֻ����һ������ */ + + memset(compress_name, 0, sizeof(compress_name)); + compress_len = dns_compress_rr_str(query->qname,strlen((char *)(query->qname)), compress_name); + memcpy(payload, compress_name, compress_len); + + used_len += compress_len ; + + tqtype = ntohs(query->qtype); + memcpy(payload+used_len, &(tqtype), sizeof(query->qtype)); + used_len += sizeof(query->qtype); + + tqclass = ntohs(query->qclass); + memcpy(payload+used_len, &(tqclass), sizeof(query->qclass)); + used_len += sizeof(query->qclass); + + return used_len; +} + + +int set_cheat_pkt_rr_pdata_type_str(unsigned char *payload, int payload_len, cheat_pkt_opt_t *cheat_opt) +{ + int used_len = 0; + unsigned int seg_32 = 0; + unsigned short seg_16 = 0; + unsigned short q_class = 1; + unsigned short compress_len = 0; + u_char compress_name[DNS_MAX_NAME+1]; + + seg_16 = htons(0xc00c); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + /* type: 2byte */ + seg_16 = htons(cheat_opt->res_type); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + /*class: 2byte */ + seg_16 = htons(q_class); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + /*TTL: 2byte */ + seg_32 = htonl(cheat_opt->ttl); + memcpy(payload + used_len, &seg_32, sizeof(seg_32)); + used_len += sizeof(seg_32); + + memset(compress_name, 0, sizeof(compress_name)); + compress_len = dns_compress_rr_str(cheat_opt->res_info, cheat_opt->res_len, compress_name); + + /*RR data length*/ + seg_16 = htons(compress_len); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + memcpy(payload + used_len, compress_name, compress_len); + used_len += compress_len; + + return used_len; +} + +int set_cheat_pkt_rr_pdata_type_ip(unsigned char *payload, int payload_len, cheat_pkt_opt_t *cheat_opt) +{ + int used_len = 0; + unsigned int seg_32 = 0; + unsigned short seg_16 = 0; + unsigned short q_class = 1; + + seg_16 = htons(0xc00c); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + /* type: 2byte */ + seg_16 = htons(cheat_opt->res_type); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + /*class: 2byte */ + seg_16 = htons(q_class); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + /*TTL: 2byte */ + seg_32 = htonl(cheat_opt->ttl); + memcpy(payload + used_len, &seg_32, sizeof(seg_32)); + used_len += sizeof(seg_32); + + /*RR data length*/ + seg_16 = htons(cheat_opt->res_len); + memcpy(payload + used_len, &seg_16, sizeof(seg_16)); + used_len += sizeof(seg_16); + + memcpy(payload + used_len, (char *)cheat_opt->res_info, cheat_opt->res_len); + used_len += cheat_opt->res_len; + + return used_len; +} + + +int set_cheat_pkt_header(dns_hdr_t *dns_hdr) +{ + dns_hdr->qr = 1; // 1bit: Response + dns_hdr->opcode = 0; // 4bits: Query + dns_hdr->aa = 0; // 1bit: authoritative answer + dns_hdr->tc = 0; // 1bit: Not truncated + dns_hdr->rd = 1; // 1bit: Recursion Desired + dns_hdr->ra = 1; // 1bit: Recursion Available + dns_hdr->z = 0; // 3bits: Reserved for future use: Must be zero in all queries and responses + dns_hdr->rcode = 0; // 4bits: 0: No error condition + + dns_hdr->id = htons(dns_hdr->id); + dns_hdr->qdcount = htons(dns_hdr->qdcount); // 16bits: QDCOUNT: number of questions + dns_hdr->ancount = htons(dns_hdr->ancount); // 16bits: ANCOUNT: number of answer resource records + dns_hdr->aucount = htons(dns_hdr->aucount); // 16bits: NSCOUNT: number of authority resource records + dns_hdr->adcount = htons(dns_hdr->adcount); // 16bits: ARCOUNT: number of additional resource records + + return 0; +} + +int build_cheat_pkt(unsigned char *payload, int payload_len, dns_query_question_t *query_question, cheat_pkt_opt_t *cheat_opt, int cheat_opt_num) +{ + int i = 0, rr_count = 0; + dns_hdr_t *dns_hdr = NULL; + int used_len = 0; + + dns_hdr = (dns_hdr_t *)payload; + + used_len += sizeof(dns_hdr_t); + used_len += set_cheat_pkt_question(payload+used_len, payload_len-used_len, query_question, dns_hdr->qdcount); + + rr_count = dns_hdr->adcount + dns_hdr->ancount + dns_hdr->aucount; + + for(i = 0; i < rr_count; i++) + { + switch(cheat_opt[i].res_type) + { + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + used_len += set_cheat_pkt_rr_pdata_type_ip(payload+used_len, payload_len, &cheat_opt[i]); + break; + case DNS_TYPE_CNAME: + case DNS_TYPE_NS: + used_len += set_cheat_pkt_rr_pdata_type_str(payload+used_len, payload_len, &cheat_opt[i]); + break; + } + + if(used_len > payload_len) + { + return -1; + } + } + + set_cheat_pkt_header(dns_hdr); + + return used_len; +} + + +int check_port(struct layer_addr addr, unsigned short port) +{ + struct stream_tuple4_v4 *tpl4 = NULL; + struct stream_tuple4_v6 *tpl6 = NULL; + + switch(addr.addrtype) + { + case ADDR_TYPE_IPV4: + tpl4=addr.tuple4_v4; + if((ntohs(tpl4->source) != port) && (ntohs(tpl4->dest) != port)) + { + return 0; + } + break; + case ADDR_TYPE_IPV6: + tpl6=addr.tuple4_v6; + if((ntohs(tpl6->source) != port) && (ntohs(tpl6->dest) != port)) + { + return 0; + } + break; + default: + break; + } + + return 1; +} + +void free_dns_info(dns_info_t *dns_info) +{ + int i = 0; + + if(dns_info->query_question != NULL) + { + free(dns_info->query_question); + dns_info->query_question = NULL; + } + + if(dns_info->rr != NULL && dns_info->rr_count > 0) + { + for(i = 0; i < dns_info->rr_count; i++) + { + switch(dns_info->rr[i].type) + { + case DNS_TYPE_NSEC3: + if(dns_info->rr[i].rdata.cname != NULL) + { + if(dns_info->rr[i].rdata.nsec3->salt_value != NULL) + { + free(dns_info->rr[i].rdata.nsec3->salt_value); + dns_info->rr[i].rdata.nsec3->salt_value = NULL; + } + + if(dns_info->rr[i].rdata.nsec3->next_hash_owner != NULL) + { + free(dns_info->rr[i].rdata.nsec3->next_hash_owner); + dns_info->rr[i].rdata.nsec3->next_hash_owner = NULL; + } + + free(dns_info->rr[i].rdata.cname); + dns_info->rr[i].rdata.cname = NULL; + } + break; + default: + if(dns_info->rr[i].rdata.cname != NULL) + { + free(dns_info->rr[i].rdata.cname); + dns_info->rr[i].rdata.cname = NULL; + } + break; + } + } + + free(dns_info->rr); + dns_info->rr = NULL; + } +} +int get_dns_hdr_info(dns_hdr_t *dns_hdr, char *payload) +{ + dns_hdr_t *tmp = ((dns_hdr_t *)payload); + memset(dns_hdr, 0, sizeof(dns_hdr_t)); +/* + dns_hdr->qr = ntohs(tmp->qr); + dns_hdr->opcode= ntohs(tmp->opcode); + dns_hdr->aa = ntohs(tmp->aa); + dns_hdr->tc = ntohs(tmp->tc); + dns_hdr->rd = ntohs(tmp->rd); + dns_hdr->ra = ntohs(tmp->ra); + dns_hdr->z = ntohs(tmp->z); + dns_hdr->rcode = ntohs(tmp->rcode); +*/ + dns_hdr->qr = tmp->qr; + dns_hdr->opcode= tmp->opcode; + dns_hdr->aa = tmp->aa; + dns_hdr->tc = tmp->tc; + dns_hdr->rd = tmp->rd; + dns_hdr->ra = tmp->ra; + dns_hdr->z = tmp->z; + dns_hdr->rcode = tmp->rcode; + + dns_hdr->id = ntohs(tmp->id); + dns_hdr->qdcount = ntohs(tmp->qdcount); + dns_hdr->ancount = ntohs(tmp->ancount); + dns_hdr->aucount = ntohs(tmp->aucount); + dns_hdr->adcount = ntohs(tmp->adcount); + + return 0; +} +int get_rr_type_nsec3(char **ptr, nsec3_t *nsec3, char *end) +{ + nsec3->hash_algo = *(unsigned char *)*ptr; + *ptr += 1; + nsec3->flags= *(unsigned char *)*ptr; + *ptr += 1; + NS_GET16(nsec3->iteration, *ptr); + nsec3->salt_len = *(unsigned char *)*ptr; + *ptr += 1; + nsec3->salt_value = (unsigned char *)calloc(1, nsec3->salt_len+1); /* jump nsec3_t */ + memcpy(nsec3->salt_value, *ptr, nsec3->salt_len); + *ptr += nsec3->salt_len; /* jump salt_value */ + + nsec3->hash_len = *(unsigned char *)*ptr; + *ptr += 1; + nsec3->next_hash_owner = (unsigned char *)calloc(1, nsec3->hash_len+1); + memcpy(nsec3->next_hash_owner, *ptr, nsec3->hash_len); + *ptr += nsec3->hash_len;/* jump next_hash_owner */ + + return 0; +} + +int get_rr_signer(unsigned char ** ptr, unsigned char *buf, int buflen, char* end) +{ + unsigned char *p = NULL; + int len = 0, i = 0; + + p = *ptr; + if(0 == p[0]) + { + len = strlen("Root"); + memcpy(buf, "Root", len); + buf[len] = '\0'; + *ptr += 1; + return 1; + } + + p = *ptr; + *ptr = NULL; + len = 0; + + while(1) + { + len++; + if(0x03 == p[0]) + { + p += 1; + continue; + } + + buf[i++] = p[0]; + p += 1; + + if(0 == p[0]) + { + len++; + p += 1; + break; + } + } + + *ptr = p; + buf[i] = '\0'; + + return len; +} +int get_rr_type_rrsig(char **ptr, rrsig_t *rrsig, char *end) +{ + NS_GET16(rrsig->type_covered, *ptr); + rrsig->algo = *(unsigned char *)ptr; + *ptr += 1; + rrsig->labels = *(unsigned char *)ptr; + *ptr += 1; + NS_GET32(rrsig->original_ttl, *ptr); + NS_GET32(rrsig->sig_expiration, *ptr); + NS_GET32(rrsig->sig_inception, *ptr); + NS_GET16(rrsig->key_tag, *ptr); + + return 0; +} + +int get_rr_type_wks(char **ptr, wks_t *wks, char *end) +{ + if(* ptr + 4 > end) return -1; + NS_GET32(wks->addr, * ptr); + if(* ptr + 1 > end) return -1; + wks->protocol = *(unsigned char *)ptr; + *ptr += 1; + wks->bitmap = *(u_char**)ptr; + + return 0; +} + +int get_rr_type_soa(char *msg, char **ptr, soa_t *soa, char *end) +{ + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, soa->mname, sizeof(soa->mname), end)) + return -1; + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, soa->rname, sizeof(soa->rname), end)) + return -1; + + if(* ptr + 4 > end) return -1; + NS_GET32(soa->serial, *ptr); + if(* ptr + 4 > end) return -1; + NS_GET32(soa->refresh, *ptr); + if(* ptr + 4 > end) return -1; + NS_GET32(soa->retry, *ptr); + if(* ptr + 4 > end) return -1; + NS_GET32(soa->expire, *ptr); + if(* ptr + 4 > end) return -1; + NS_GET32(soa->minimum, *ptr); + + return 0; +} + +int get_rr_type_info(char **ptr, hinfo_t *hinfo, char *end) +{ + int len = 0; + hinfo->cpu_len = ((unsigned char *)ptr)[0]; + *ptr += 1; + len = MIN(hinfo->cpu_len, sizeof(DNS_HINFO_MAX_CPU-1)); + memcpy((char *)hinfo->cpu, *ptr, len); + *ptr += hinfo->cpu_len; + hinfo->cpu_len = len; + + hinfo->os_len = ((unsigned char *)ptr)[0]; + *ptr += 1; + len = MIN(hinfo->os_len, sizeof(DNS_HINFO_MAX_OS-1)); + memcpy((char *)hinfo->os, *ptr, len); + *ptr += hinfo->os_len; + hinfo->os_len = len; + + return 0; +} + +int get_decompressed_name(char * msg, unsigned char**ptr, unsigned char *buf, int buflen, char *end) +{ + unsigned char *p = NULL; + int index = 0, len = 0; + int np = 0, tot_len = 0; + + p = *ptr; + *ptr = NULL; + index = 0; + np = 0; + while(1) + { + if(0 == p[0]) + { + break; + } + + if(0x0c0 == (p[0] & 0x0c0)) + { + if(p + 2 > (unsigned char *)end) + return -1; + + len = ((p[0] & 0x03f) << 8) + p[1]; + + if(NULL == * ptr) + { + tot_len += 2; + *ptr = p + 2; + } + + p =(unsigned char*) msg + len; + if(p > (unsigned char *)end) + return -1; + + /* too many pointers. */ + if(np ++ > 16) + return -1; + + continue; + } + + + len = p[0]; + p ++; + tot_len++; + + if(p + len > (unsigned char *)end) + return -1; + + if(index + len >= buflen - 1) + return -1; + + memcpy(buf + index, p, len); + index += len; + buf[index ++] = '.'; + p += len; + tot_len +=len; + } + + if(NULL == *ptr) + { + *ptr = p + 1; + tot_len++; + } + /* + * omit last '.' + */ + if(index>0) + { + buf[index-1]='\0'; + } + else + { + buf[0]='\0'; + } + + return tot_len; +} + + +int get_rr_domain( char * msg,unsigned char ** ptr, unsigned char * buf, int buflen, char * end) +{ + return get_decompressed_name(msg, ptr, buf, buflen, end); +} + +int get_rr_common_field(char *msg, char **ptr, dns_rr_t *rr, char *end) +{ + char * p = NULL; + if(*ptr==NULL) + { + return -1; + } + + get_rr_domain(msg, (unsigned char**)ptr, rr->name, DNS_MAX_NAME+1, end); +#if 0 + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->name, DNS_MAX_NAME+1, end)) + { + return -1; + } +#endif + if(* ptr + 2 > end) + { + return -1; + } + NS_GET16(rr->type, * ptr); + if(* ptr + 2 > end) + { + return -1; + } + + NS_GET16(rr->rr_class, * ptr); + + if(DNS_CLASS_UNKNOWN == rr->rr_class) + { + return -1; + } + + if(* ptr + 4 > end) + { + return -1; + } + NS_GET32(rr->ttl, * ptr); + if(* ptr + 2 > end) + { + return -1; + } + NS_GET16(rr->rdlength, * ptr); + p = * ptr + rr->rdlength; + if(p > end) + { + return -1; + } + + return 0; +} + +int callback_dns_business_plug(struct streaminfo *a_stream, void **pme, void *info, int prot_flag, int session_state, int thread_seq, void *a_packet) +{ + stSessionInfo sessionInfo; + save_dns_business_info_t *apme = (save_dns_business_info_t *)*pme; + + memset(&sessionInfo, 0, sizeof(stSessionInfo)); + + sessionInfo.plugid = dns_plugid; + sessionInfo.session_state = session_state; + sessionInfo.prot_flag = prot_flag; + sessionInfo.app_info = (void *)info; + PROT_PROCESS(&sessionInfo, &apme->business_pme, thread_seq, a_stream, a_packet); + + return 0; +} + +int get_dns_query_question(char *msg, char **ptr, dns_query_question_t *q, char *end) +{ + int used_len = 0; + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, q->qname, DNS_MAX_NAME+1, end)) + { + return -1; + } + + used_len = strlen((char *)q->qname); + if(q->qname[used_len-1]=='.') + return -2; + + if(* ptr + 2 > end) + { + return -1; + } + + NS_GET16(q->qtype, *ptr); + + if(* ptr + 2 > end) + { + return -1; + } + + NS_GET16(q->qclass, *ptr); + + return 0; +} + +int get_one_resource_record(char * msg, char ** ptr, dns_rr_t * rr, char * end) +{ + //int salt_len = 0, hash_len = 0; + unsigned int len = 0, byte = 0; + unsigned char *original_ptr = NULL; + + switch(rr->type) + { + case DNS_TYPE_CNAME: + original_ptr = (unsigned char*)*ptr; + rr->rdata.cname = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.cname, DNS_MAX_NAME+1, end)) + { + return 0; + } + + break; + case DNS_TYPE_HINFO: + rr->rdata.hinfo = (hinfo_t *)calloc(1, sizeof(hinfo_t)); + if(0 != get_rr_type_info(ptr, rr->rdata.hinfo, end)) + { + return 0; + } + break; + case DNS_TYPE_MB: + rr->rdata.mb = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.mb, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_MD: + rr->rdata.md = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg, (unsigned char**) ptr, rr->rdata.md, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_MF: + rr->rdata.mf = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.mf, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_MG: + rr->rdata.mg = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.mg, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_MINFO: + rr->rdata.minfo = (minfo_t *)calloc(1, sizeof(minfo_t)); + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.minfo->rmailbx, DNS_MAX_NAME+1, end)) + return 0; + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.minfo->emailbx, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_MR: + rr->rdata.mr = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg,(unsigned char**) ptr, rr->rdata.mr, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_MX: + if(*ptr + 2 > end) return 0; + rr->rdata.mx = (mx_t *)calloc(1, sizeof(mx_t)); + NS_GET16(rr->rdata.mx->preference, *ptr); + if(rr->rdlength - 2 < ((unsigned char *)*ptr)[0]) + { + if(rr->rdlength < 2) + { + *ptr += rr->rdlength; + break; + } + len = MIN(DNS_MAX_NAME-1, rr->rdlength-2);/*size=1byte*/ + memcpy(rr->rdata.mx->exchange, *ptr, len); /* error labels */ + *ptr += rr->rdlength-2; + } + else + { + if(0 >= get_rr_domain(msg,(unsigned char**) ptr, rr->rdata.mx->exchange, DNS_MAX_NAME+1, end)) + return 0; + } + break; + case DNS_TYPE_NS: + rr->rdata.ns = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg,(unsigned char**) ptr, rr->rdata.ns, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_PTR: + rr->rdata.ptr = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.ptr, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_SOA: + original_ptr = (unsigned char*)*ptr; + rr->rdata.soa = (soa_t *)calloc(1, sizeof(soa_t)); + if(0 != get_rr_type_soa(msg, ptr, rr->rdata.soa, end)) + return 0; + if((char *)original_ptr+rr->rdlength!=*ptr) + { + *ptr=(char *)original_ptr+rr->rdlength; + } + break; + case DNS_TYPE_A: + if(* ptr + 4 > end) return 0; + rr->rdata.a = (u_char *)calloc(1, NS_INT32SZ+1); + memcpy(rr->rdata.a, *ptr, NS_INT32SZ); + (*ptr) += NS_INT32SZ; + break; + case DNS_TYPE_AAAA: + if(* ptr + 16 > end) return -1; + rr->rdata.aaaa = (u_char *)calloc(1, 17); + memcpy(rr->rdata.aaaa, *ptr, 16); + (*ptr)+=16; + break; + case DNS_TYPE_DNAME: + rr->rdata.dname = (u_char *)calloc(1, DNS_MAX_NAME+1); + if(0 >= get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.dname, DNS_MAX_NAME+1, end)) + return 0; + break; + case DNS_TYPE_ISDN: + rr->rdata.isdn = (u_char *)calloc(1, 1); + memcpy(rr->rdata.isdn, *ptr, sizeof(u_char)); + (*ptr)+=1; + break; + case DNS_TYPE_TXT: + rr->rdata.txt = (txt_t *)calloc(1, sizeof(txt_t)); + len = MIN(DNS_MAX_NAME-1, rr->rdlength-1);/*size=1byte*/ + memcpy(rr->rdata.txt->txt, *ptr+1, len); + rr->rdata.txt->size = len; + *ptr += rr->rdlength; + break; + case DNS_TYPE_NULL: + rr->rdata.null = (null_t *)calloc(1, sizeof(null_t)); + len = MIN(DNS_MAX_NAME-1, rr->rdlength-1); /*size=1byte*/ + memcpy(rr->rdata.null->null, *ptr+1, len); + rr->rdata.null->size = len; + *ptr += rr->rdlength; + break; + case DNS_TYPE_WKS: + rr->rdata.wks = (wks_t *)calloc(1, sizeof(wks_t)); + if(0 != get_rr_type_wks(ptr, rr->rdata.wks, end)) + return 0; + rr->rdata.wks->size = rr->rdlength - 5; + *ptr += rr->rdlength - 5; + case DNS_TYPE_SRV: + rr->rdata.srv = (srv_t *)calloc(1, sizeof(srv_t)); + NS_GET16(rr->rdata.srv->priority, *ptr); + NS_GET16(rr->rdata.srv->weight, *ptr); + NS_GET16(rr->rdata.srv->port, *ptr); + if(0 >= get_rr_domain(msg,(unsigned char**) ptr, rr->rdata.srv->target, DNS_MAX_TARGET, end)) + return 0; + break; + case DNS_TYPE_OPT: + break; + case DNS_TYPE_DS: + case DNS_TYPE_DLV: + if(* ptr + 4 > end) return 0; + rr->rdata.ds = (ds_t *)calloc(1, sizeof(ds_t)); + NS_GET16(rr->rdata.ds->key_tag, *ptr); + rr->rdata.ds->algo = *(unsigned char *)ptr; + *ptr += 1; + rr->rdata.ds->digest_type = *(unsigned char *)ptr; + *ptr += 1; + rr->rdata.ds->digest = *(u_char**)ptr; + rr->rdata.ds->digest_len = rr->rdlength - 4; + *ptr += rr->rdlength - 4; + break; + case DNS_TYPE_RRSIG: + if(* ptr + 18 > end) return 0; + rr->rdata.rrsig = (rrsig_t *)calloc(1, sizeof(rrsig_t)); + get_rr_type_rrsig(ptr, rr->rdata.rrsig, end); + len = get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.rrsig->signer_name, DNS_MAX_SIGNER_NAME, end); + if(len <= 0) + { + return -1; + } + rr->rdata.rrsig->signature = *(u_char**)ptr; + rr->rdata.rrsig->signature_len = rr->rdlength - 18 - len; + *ptr += rr->rdlength - 18 - len; + break; + case DNS_TYPE_NSEC: + original_ptr = (unsigned char*)*ptr; + rr->rdata.nsec = (nsec_t *)calloc(1, sizeof(nsec_t)); + len = get_rr_domain(msg, (unsigned char**)ptr, rr->rdata.nsec->next_domain, DNS_MAX_OWNER, end); + if(len <= 0) + { + return -1; + } + + if((original_ptr+rr->rdlength != (unsigned char*)*ptr) && (*ptr != NULL)) + { + NS_GET16(len, *ptr); + byte = MIN(DNS_MAX_MAPS-1, len); + memcpy(rr->rdata.nsec->type_bit_maps, *ptr, byte); + *ptr += len; + rr->rdata.nsec->maps_len = len; + len = byte; + + byte = ((unsigned char *)ptr)[0]; + if((byte&0xFF) == 0xFF || byte == 128) + { + *ptr += 1; /* jump 0xFF */ + byte = ((unsigned char *)ptr)[0]; + *ptr += 1; /* jump 1 byte of len */ + len = MIN(DNS_MAX_MAPS-1-len, byte); + memcpy(rr->rdata.nsec->type_bit_maps+rr->rdata.nsec->maps_len, *ptr, len); + *ptr += byte; /* jump byte */ + rr->rdata.nsec->maps_len += len; + } + } + break; + case DNS_TYPE_DNSKEY: + if(* ptr + 4 > end) return 0; + rr->rdata.dnskey = (dnskey_t *)calloc(1, sizeof(dnskey_t)); + NS_GET16(rr->rdata.dnskey->flags, *ptr); + rr->rdata.dnskey->protocol = *(unsigned char *)ptr; + *ptr += 1; + rr->rdata.dnskey->algo = *(unsigned char *)ptr; + *ptr += 1; + rr->rdata.dnskey->public_key = *(u_char**)ptr; + rr->rdata.dnskey->public_key_len = rr->rdlength - 4;/* sizeof(flags)+sizeof(protocol)+sizeof(algo) */ + *ptr += rr->rdlength - 4; /* todo add log */ + break; + case DNS_TYPE_NSEC3: + if(* ptr + 5 > end) return 0; + original_ptr = (unsigned char*)*ptr; + //salt_len = *(unsigned char *)(*ptr+4); /* salt length */ + //hash_len = *(salt_len + (unsigned char *)(*ptr+5)); /* hash length */ + rr->rdata.nsec3 = (nsec3_t *)calloc(1, sizeof(nsec3_t)); + get_rr_type_nsec3(ptr, rr->rdata.nsec3, end); + + if((original_ptr+rr->rdlength != (unsigned char*)*ptr) && (*ptr != NULL)) + { + NS_GET16(len, *ptr); + byte = MIN(DNS_MAX_MAPS-1, len); + memcpy( rr->rdata.nsec3->type_bit_maps, *ptr, byte); + *ptr += len; + rr->rdata.nsec3->maps_len = byte; + len = byte; + + byte = ((unsigned char *)*ptr)[0]; + if((byte&0xFF) == 0xFF || byte == 128) + { + *ptr += 1; /* jump 0xFF */ + byte = ((unsigned char *)*ptr)[0]; + *ptr += 1; /* jump 1 byte of len */ + len = MIN(DNS_MAX_MAPS-1-len, byte); + memcpy(rr->rdata.nsec3->type_bit_maps+rr->rdata.nsec3->maps_len, *ptr, len); + *ptr += byte; /* jump byte */ + rr->rdata.nsec3->maps_len += len; + } + } + break; + case DNS_TYPE_NSEC3PARAM: + rr->rdata.nsec3param = (nsec3param_t *)calloc(1, sizeof(nsec3param_t)); + rr->rdata.nsec3param->hash_algo = *(unsigned char *)ptr; + *ptr += 1; + rr->rdata.nsec3param->flags = *(unsigned char *)ptr; + *ptr += 1; + NS_GET16(rr->rdata.nsec3param->iteration, *ptr); + rr->rdata.nsec3param->salt_len = rr->rdlength -4-1; + *ptr += 1; + rr->rdata.nsec3param->salt_value = *(u_char**)ptr; + *ptr += rr->rdlength-5; + break; + default: + *ptr += rr->rdlength; + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_INFO, "get_one_rr", "No support respone type, type: %d", rr->type); + break; + } + + return 1; +} + +int parse_query_question(struct streaminfo *a_stream, dns_info_t *dns_info, char *payload, int payload_len, char **cur_pos) +{ + int ret = 0; + + if(1 != dns_info->hdr_info.qdcount) + { + /* ����һ�β�ѯ�������������������(S<==>S)��������δ����(��ѧ����������) */ + return APP_STATE_DROPME; + } + + dns_info->query_question = (dns_query_question_t *)calloc(dns_info->hdr_info.qdcount, sizeof(dns_query_question_t)); + + if(0 != (ret = get_dns_query_question(payload, cur_pos, dns_info->query_question, payload+payload_len))) + { + if(ret == -2) + { + dns_save_error_pkt(a_stream, DNS_ERROR_QUESTION); + } + return APP_STATE_DROPME; + } + + return APP_STATE_GIVEME; +} + + +int parse_resource_record(struct streaminfo *a_stream, dns_info_t *dns_info, char *payload, int payload_len, char **cur_pos, int rr_type) +{ + int i = 0; + + switch(rr_type) + { + case DNS_RR_TYPE_ALL: + dns_info->rr_count = dns_info->hdr_info.ancount + dns_info->hdr_info.adcount + dns_info->hdr_info.aucount; + break; + case DNS_RR_TYPE_ANS: + dns_info->rr_count = dns_info->hdr_info.ancount; + break; + case DNS_RR_TYPE_AUTH: + dns_info->rr_count = dns_info->hdr_info.ancount; + /* todo */ + dns_info->rr_count = dns_info->hdr_info.aucount; + break; + case DNS_RR_TYPE_ADD: + dns_info->rr_count = dns_info->hdr_info.ancount + dns_info->hdr_info.aucount; + /* todo */ + dns_info->rr_count = dns_info->hdr_info.adcount; + break; + default: + break; + } + + if(dns_info->rr_count == 0) + { + return APP_STATE_GIVEME; + } + dns_info->rr = (dns_rr_t *)calloc(dns_info->rr_count, sizeof(dns_rr_t)); + + for(i = 0; i < dns_info->rr_count; i++) + { + if((unsigned char *)*cur_pos >= (unsigned char *)payload+payload_len || (unsigned char *)*cur_pos < (unsigned char *)payload) + { + dns_save_error_pkt(a_stream, DNS_ERROR_PAYLOAD_SHORT); + return APP_STATE_DROPME; + } + + if(0 != get_rr_common_field(payload, cur_pos, &dns_info->rr[i], payload+payload_len)) + { + if(dns_info->rr[i].rr_class == DNS_CLASS_UNKNOWN) + { + dns_save_error_pkt(a_stream, DNS_ERROR_CLASS_UNKNOWN); + return APP_STATE_DROPME; /* error packet */ + } + else + { + dns_save_error_pkt(a_stream, DNS_ERROR_UNKNOWN); + dns_info->rr_count -= 1; + i -= 1; + continue; + } + } + + if(dns_info->rr[i].rdlength == 0) + { + continue; + } + + if(!get_one_resource_record(payload, cur_pos, &dns_info->rr[i], payload+payload_len)) + { + if(dns_info->rr[i].rdata.cname != NULL) + { + free(dns_info->rr[i].rdata.cname); + dns_info->rr[i].rdata.cname = NULL; + } + dns_save_error_pkt(a_stream, DNS_ERROR_RR); + dns_info->rr_count -= 1; + i -= 1; + } + } + + assert(i==dns_info->rr_count); + + return APP_STATE_GIVEME; +} + +int parse_dns_protocol(struct streaminfo *a_stream, unsigned char opstate, char *payload, int payload_len, void **pme, int thread_seq, void *a_packet) +{ + int i = 0; + int session_state = SESSION_STATE_PENDING; + int ret = APP_STATE_GIVEME; + char *cur_pos = NULL; + dns_info_t dns_info; + unsigned long long register_flag = dns_register_flag; + save_dns_business_info_t *context = (save_dns_business_info_t *)(*pme); + + if(payload_len < 12 ) + { + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[ERR_PKT], 0, FS_OP_ADD, 1); + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_FATAL, "parse_dns_protocol", "tuple4: %s payload_len < 12", printaddr(&a_stream->addr, thread_seq)); + return APP_STATE_DROPME; + } + + memset(&dns_info, 0, sizeof(dns_info_t)); + get_dns_hdr_info(&dns_info.hdr_info, payload); +#if 0 + if(dns_info.hdr_info.tc == 1 || (dns_info.hdr_info.rcode != 0 && 1 == dns_info.hdr_info.qr)) + { + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[ERR_PKT], 0, FS_OP_ADD, 1); + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_FATAL, "parse_dns_protocol", + "TC: %u, RCODE: %u, tuple4: %s", dns_info.hdr_info.tc, dns_info.hdr_info.rcode, printaddr(&a_stream->addr, thread_seq)); + return APP_STATE_DROPME; /* ���ضϵ�DNS��UDP�����ݲ����� */ + } +#endif + cur_pos = payload + sizeof(dns_hdr_t); + + for(i = 0; i < dns_register_flag_num; i++) + { + if(opstate != OP_STATE_CLOSE) + { + if(context->session_state&SESSION_STATE_PENDING) + { + session_state = SESSION_STATE_DATA; + } + else + { + session_state = SESSION_STATE_PENDING|SESSION_STATE_DATA; + } + context->session_state = SESSION_STATE_PENDING|SESSION_STATE_DATA; + } + else + { + if(context->session_state&SESSION_STATE_PENDING) + { + session_state = SESSION_STATE_CLOSE; + } + else + { + session_state = SESSION_STATE_PENDING|SESSION_STATE_DATA|SESSION_STATE_CLOSE; + } + } + #if 0 + switch(opstate) + { + case OP_STATE_PENDING: + session_state = SESSION_STATE_PENDING|SESSION_STATE_DATA; + break; + case OP_STATE_DATA: + session_state = SESSION_STATE_DATA; + break; + case OP_STATE_CLOSE: + session_state = SESSION_STATE_CLOSE; + break; + default: + return APP_STATE_DROPME; + } + #endif + if(register_flag&DNS_ALL) + { + register_flag = SET_BIT(register_flag, DNS_ALL); + + ret = parse_query_question(a_stream, &dns_info, payload, payload_len, &cur_pos); + if(ret == APP_STATE_DROPME) + { + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[ERR_PKT], 0, FS_OP_ADD, 1); + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_DEBUG, "parse_dns_protocol", "parse_query_question return APP_STATE_DROPME, tuple4: %s, question_num: %d", printaddr(&a_stream->addr, thread_seq), dns_info.hdr_info.qdcount); + free_dns_info(&dns_info); + return APP_STATE_DROPME; + } + if(1 == dns_info.hdr_info.qr) /* process response packet */ + { + ret = parse_resource_record(a_stream, &dns_info, payload, payload_len, &cur_pos, DNS_RR_TYPE_ALL); + if(ret == APP_STATE_DROPME) + { + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[ERR_PKT], 0, FS_OP_ADD, 1); + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_DEBUG, "parse_dns_protocol", "parse_resource_record return APP_STATE_DROPME, tuple4: %s", printaddr(&a_stream->addr, thread_seq)); + free_dns_info(&dns_info); + return APP_STATE_DROPME; + } + } + + callback_dns_business_plug(a_stream, pme, (void *)&dns_info, DNS_ALL, session_state, thread_seq, a_packet); + } + else if((register_flag&DNS_REQ_ALL) && (0 == dns_info.hdr_info.qr)) /* process query packet */ + { + register_flag = SET_BIT(register_flag, DNS_REQ_ALL); + + ret = parse_query_question(a_stream, &dns_info, payload, payload_len, &cur_pos); + } + else if((register_flag&DNS_REQ_HDR) && (0 == dns_info.hdr_info.qr)) /* process query packet */ + { + register_flag = SET_BIT(register_flag, DNS_REQ_HDR); + } + else if((register_flag&DNS_RES_ALL) && (1 == dns_info.hdr_info.qr)) /* process response packet */ + { + register_flag = SET_BIT(register_flag, DNS_RES_ALL); + } + else if((register_flag&DNS_RES_HDR) && (1 == dns_info.hdr_info.qr)) /* process response packet */ + { + register_flag = SET_BIT(register_flag, DNS_RES_HDR); + } + else if((register_flag&DNS_RES_QUERY) && (1 == dns_info.hdr_info.qr)) /* process response packet */ + { + register_flag = SET_BIT(register_flag, DNS_RES_QUERY); + } + else if((register_flag&DNS_RES_RRS) && (1 == dns_info.hdr_info.qr)) /* process response packet */ + { + register_flag = SET_BIT(register_flag, DNS_RES_RRS); + } + else if((register_flag&DNS_RES_ANSWER) && (1 == dns_info.hdr_info.qr)) /* process response packet */ + { + register_flag = SET_BIT(register_flag, DNS_RES_ANSWER); + } + else if((register_flag&DNS_RES_AUTH) && (1 == dns_info.hdr_info.qr)) /* process response packet */ + { + register_flag = SET_BIT(register_flag, DNS_RES_AUTH); + } + else if((register_flag&DNS_RES_ADD) && (1 == dns_info.hdr_info.qr)) /* process response packet */ + { + register_flag = SET_BIT(register_flag, DNS_RES_ADD); + } + else + { + + } + + if(i != 0) + continue; + + if(1 == dns_info.hdr_info.qr) /* process response packet */ + { + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[R_PKT], 0, FS_OP_ADD, 1); + } + else + { + switch(dns_info.query_question->qtype) + { + case DNS_TYPE_A: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[Q_A], 0, FS_OP_ADD, 1); + break; + case DNS_TYPE_AAAA: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[Q_AAAA], 0, FS_OP_ADD, 1); + break; + case DNS_TYPE_CNAME: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[Q_CNAME], 0, FS_OP_ADD, 1); + break; + default: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[Q_UNKNOWN], 0, FS_OP_ADD, 1); + break; + } + + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[Q_PKT], 0, FS_OP_ADD, 1); + } + } + + free_dns_info(&dns_info); + + return APP_STATE_GIVEME; +} + +char DNS_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a_packet) +{ + int payload_len = 0; + char *payload = NULL; + struct udpdetail *udp_detail = NULL; + + if(!check_port(a_udp->addr, DNS_PORT)) + { + return APP_STATE_DROPME; + } + + udp_detail = (struct udpdetail *)a_udp->pudpdetail; + payload_len = udp_detail->datalen; + payload = (char *)udp_detail->pdata; + + switch(a_udp->opstate) + { + case OP_STATE_PENDING: + if(*pme == NULL) + { + *pme = dictator_malloc(thread_seq, sizeof(save_dns_business_info_t)); + memset(*pme, 0, sizeof(save_dns_business_info_t)); + } + /* no break here!!!! */ + case OP_STATE_DATA: + switch(a_udp->addr.addrtype) + { + case ADDR_TYPE_IPV4: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V4_U_PPS], 0, FS_OP_ADD, 1); + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V4_U_BPS], 0, FS_OP_ADD, payload_len); + break; + case ADDR_TYPE_IPV6: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V6_U_PPS], 0, FS_OP_ADD, 1); + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V6_U_BPS], 0, FS_OP_ADD, payload_len); + break; + default: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[PKT_UNKNOWN], 0, FS_OP_ADD, 1); + return APP_STATE_DROPME; + break; + } + + parse_dns_protocol(a_udp, a_udp->opstate, payload, payload_len, pme, thread_seq, a_packet); + break; + case OP_STATE_CLOSE: + callback_dns_business_plug(a_udp, pme, NULL, DNS_ALL, SESSION_STATE_CLOSE, thread_seq, a_packet); + dictator_free(thread_seq, *pme); + *pme = NULL; + break; + } + + return APP_STATE_GIVEME; +} + + +char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a_packet) +{ + int payload_len = 0; + char *payload = NULL; + struct tcpdetail* tcp_detail = (struct tcpdetail*)a_tcp->pdetail; + + if(!check_port(a_tcp->addr, DNS_PORT)) + { + return APP_STATE_DROPME; + } + + tcp_detail = (struct tcpdetail *)a_tcp->ptcpdetail; + payload_len = tcp_detail->datalen; + payload = (char *)tcp_detail->pdata; + + payload_len -= 2; /* 2015-09-29 lijia add, TCPЭ��ͷ��ǰ��2���ֽڳ�����Ϣ */ + payload += 2; /* 2015-09-29 lijia add, TCPЭ��ͷ��ǰ��2���ֽڳ�����Ϣ */ + + switch(a_tcp->opstate) + { + case OP_STATE_PENDING: /* ��δ������������Ϣ */ + if((NULL == tcp_detail->pdata) || (0 == tcp_detail->datalen)) + { + return APP_STATE_GIVEME; + } + + if(*pme == NULL) + { + *pme = dictator_malloc(thread_seq, sizeof(save_dns_business_info_t)); + memset(*pme, 0, sizeof(save_dns_business_info_t)); + } + /* no break here!!!! */ + case OP_STATE_DATA: + + switch(a_tcp->addr.addrtype) + { + case ADDR_TYPE_IPV4: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V4_T_PPS], 0, FS_OP_ADD, 1); + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V4_T_BPS], 0, FS_OP_ADD, payload_len); + break; + case ADDR_TYPE_IPV6: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V6_T_PPS], 0, FS_OP_ADD, 1); + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[V6_T_BPS], 0, FS_OP_ADD, payload_len); + break; + default: + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[PKT_UNKNOWN], 0, FS_OP_ADD, 1); + return APP_STATE_DROPME; + break; + } +#if 0 + if((tcp_detail->serverbytes < 2) ||(tcp_detail->clientbytes >= 1500)) + { + FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[ERR_PKT], 0, FS_OP_ADD, 1); + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_DEBUG, "TCP_ENTRY", + "tuple4: %s PKT size(S: %d/C: %d) is too litter or bigger", printaddr(&a_tcp->addr, thread_seq), tcp_detail->serverbytes, tcp_detail->clientbytes); + return APP_STATE_GIVEME; + } +#endif + parse_dns_protocol(a_tcp, a_tcp->opstate, payload, payload_len, pme, thread_seq, a_packet); + break; + case OP_STATE_CLOSE: + callback_dns_business_plug(a_tcp, pme, NULL, DNS_UNKOWN, SESSION_STATE_CLOSE, thread_seq, a_packet); + dictator_free(thread_seq, *pme); + *pme = NULL; + break; + } + + return APP_STATE_GIVEME; +} + + +/**************************************************************************** +??????:DNS_INIT() +?????DNS?????????????????? +?????? +????????:plugid + ???:<0????????? +*****************************************************************************/ +int DNS_INIT() +{ + pcap_index = random(); + int i = 0, value = 1; + const char* fs_output_path="./dns_stat.log"; + memset(&g_dns_proto_info, 0, sizeof(g_dns_proto_info_t)); + + MESA_load_profile_int_def(dns_conf_file, "DNS", "STAT_CYCLE", &g_dns_proto_info.cycle_time, 2); + MESA_load_profile_int_def(dns_conf_file, "DNS", "LOG_LEVEL", &g_dns_proto_info.log_level, 30); + MESA_load_profile_string_def(dns_conf_file, "DNS", "LOG_PATH", g_dns_proto_info.log_path, MAX_LOG_PATH_LEN, NULL); + + g_dns_proto_info.logger = MESA_create_runtime_log_handle(g_dns_proto_info.log_path, g_dns_proto_info.log_level); + if(g_dns_proto_info.logger == NULL) + { + printf("********************* DNS_INIT error ***************************\n"); + return -1; + } + + g_dns_proto_info.stat_handle = FS_create_handle(); + + FS_set_para(g_dns_proto_info.stat_handle, OUTPUT_DEVICE, fs_output_path, strlen(fs_output_path)+1); + value=1;//Rewrite + FS_set_para(g_dns_proto_info.stat_handle, PRINT_MODE, &value, sizeof(value)); + value=1;//Do not create stat thread + FS_set_para(g_dns_proto_info.stat_handle, CREATE_THREAD, &value, sizeof(value)); + + FS_set_para(g_dns_proto_info.stat_handle, STAT_CYCLE, &g_dns_proto_info.cycle_time, sizeof(g_dns_proto_info.cycle_time)); + + for(i = 0; DNS_STATIS_INFO[i].str != NULL && i == (int)DNS_STATIS_INFO[i].id && i < DNS_MAX_FIELD_ID_NUM; i++) + { + g_dns_proto_info.fild_id[DNS_STATIS_INFO[i].id] = FS_register(g_dns_proto_info.stat_handle, + FS_STYLE_FIELD, + FS_CALC_CURRENT, + DNS_STATIS_INFO[i].str); + + if(g_dns_proto_info.fild_id[DNS_STATIS_INFO[i].id] == -1) + { + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_FATAL, "DNS_INIT", + "register field_id failled and str: %s", DNS_STATIS_INFO[i].str); + return -1; + } + } + + FS_start(g_dns_proto_info.stat_handle); + + return PROTID_DNS; +} + + +/**************************************************************************** +??????:DNS_DESTRORY() +?????DNS???��??????????????????? +?????? +??????? +*****************************************************************************/ +void DNS_DESTROY() +{ + printf("Hello! This is dns.so PROT_DESTORY, but i am not complete!!!\n"); +} + + +void PROT_FUNSTAT(long long protflag) +{ + int i = 0; + + if(0==protflag) + { + return; + } + + pthread_mutex_init(&dns_lock, NULL); + pthread_mutex_lock(&dns_lock); + + dns_register_flag = protflag; + + for(i = 0; i < (int)sizeof(dns_register_flag)*8; i++) + { + if((dns_register_flag>>i)&0x01) + { + dns_register_flag_num++; + } + } + + pthread_mutex_unlock(&dns_lock); + return; +} + +void GET_PLUGID(unsigned short plugid) +{ + dns_plugid = plugid; +} + +static long long get_flag_id(const char *flag_str) +{ + int i = 0; + + for(i = 0; DNS_FLAG_ID[i].str != NULL; i++) + { + if((strncasecmp(DNS_FLAG_ID[i].str, flag_str, strlen(DNS_FLAG_ID[i].str)) == 0) + && (strlen(DNS_FLAG_ID[i].str) == strlen(flag_str))) + { + return DNS_FLAG_ID[i].id; + } + } + + printf("dns.so: error! Invalid DNS FLAG:%s\n", flag_str); + + return 0; +} + +long long FLAG_CHANGE(char* raw_flag_str) +{ + long long dns_portflag = 0; + char *save_ptr; + const char *delim = " \t,"; + char *section; + char *flag_str, *parse_ptr; + + if(NULL == raw_flag_str || '\0' == *raw_flag_str){ + return 0; + } + + flag_str = (char *)malloc(strlen(raw_flag_str)+1);//add EOF + memcpy(flag_str, raw_flag_str, strlen(raw_flag_str)+1);//add EOF + + parse_ptr = flag_str; + while(((section = strtok_r(parse_ptr, delim, &save_ptr)) != NULL)) + { + dns_portflag |= get_flag_id(section); + parse_ptr = NULL; + } + + free(flag_str); + + return dns_portflag; +} + +//TODO����δʵ�� +void FLAG_PROT_FUNSTAT (long long protflag) +{ + return ; +} diff --git a/src/dns.h b/src/dns.h new file mode 100644 index 0000000..638833f --- /dev/null +++ b/src/dns.h @@ -0,0 +1,343 @@ +#ifndef DNS_ANALYSE_H +#define DNS_ANALYSE_H + +#ifndef u_char +#define u_char unsigned char +#endif + +#ifndef u_int16_t +#define u_int16_t unsigned short +#endif + +#ifndef u_int32_t +#define u_int32_t unsigned int //adjust by lqy 20070521 long to int +#endif + +#define G_DNS_TTL (rand()%1800+1800)//0.5->1hour 2015.01.26by ljp + +#define MAX_CHEAT_PKT_PAYLOAD_LEN 512 + +#define DNS_MAX_SALT 256 +#define DNS_MAX_OWNER 256 +#define DNS_MAX_MAPS 256 +#define DNS_MAX_PUBLIC_KEY 256 +#define DNS_MAX_SIGNER_NAME 256 +#define DNS_MAX_SIGNATURE 256 +#define DNS_MAX_DIGEST 256 +#define DNS_MAX_TARGET 256 + +#define DNS_HINFO_MAX_CPU 40 +#define DNS_HINFO_MAX_OS 40 +#define DNS_MAX_NAME 255 + +/* support reponse cfg type */ +#define DNS_CFG_TYPE_CNAME 0 +#define DNS_CFG_TYPE_MX 1 +#define DNS_CFG_TYPE_AUTH 2 +#define DNS_CFG_TYPE_ADDI 3 +#define DNS_CFG_TYPE_A 5 +#define DNS_CFG_TYPE_NS 6 +#define DNS_CFG_TYPE_AAAA 7 + +/* RR type */ +#define DNS_TYPE_A 1 +#define DNS_TYPE_NS 2 +#define DNS_TYPE_MD 3 +#define DNS_TYPE_MF 4 +#define DNS_TYPE_CNAME 5 +#define DNS_TYPE_SOA 6 +#define DNS_TYPE_MB 7 +#define DNS_TYPE_MG 8 +#define DNS_TYPE_MR 9 +#define DNS_TYPE_NULL 10 +#define DNS_TYPE_WKS 11 +#define DNS_TYPE_PTR 12 +#define DNS_TYPE_HINFO 13 +#define DNS_TYPE_MINFO 14 +#define DNS_TYPE_MX 15 +#define DNS_TYPE_TXT 16 +#define DNS_TYPE_ISDN 20 +#define DNS_TYPE_AAAA 28 //dns_ipv6 +#define DNS_TYPE_SRV 33 +#define DNS_TYPE_DNAME 39 +#define DNS_TYPE_OPT 41 +#define DNS_TYPE_DS 43 +#define DNS_TYPE_RRSIG 46 +#define DNS_TYPE_NSEC 47 +#define DNS_TYPE_DNSKEY 48 +#define DNS_TYPE_NSEC3 50 +#define DNS_TYPE_NSEC3PARAM 51 +#define DNS_QTYPE_AXFR 252 +#define DNS_QTYPE_MAILB 253 +#define DNS_QTYPE_MAILA 254 +#define DNS_QTYPE_ANY 255 +#define DNS_TYPE_DLV 32769 /* DSNSEC Lokkaside Validation */ + +#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_QCLASS_ANY 255 + +typedef struct _dns_hdr +{ + u_int16_t id; +#if __BYTE_ORDER == __LITTLE_ENDIAN + u_char rd:1; + u_char tc:1; + u_char aa:1; + u_char opcode:4; + u_char qr:1; + u_char rcode:4; + u_char z:3; + u_char ra:1; +#elif __BYTE_ORDER == __BIG_ENDIAN + u_char qr:1; + u_char opcode:4; + u_char aa:1; + u_char tc:1; + u_char rd:1; + u_char ra:1; + u_char z:3; + u_char rcode:4; +#endif + u_int16_t qdcount; + u_int16_t ancount; + u_int16_t aucount;//authority count + u_int16_t adcount;//additional count +} dns_hdr_t; + +typedef struct _hinfo +{ + u_char os_len; + u_char cpu_len; + u_char cpu[DNS_HINFO_MAX_CPU+1]; + u_char os[DNS_HINFO_MAX_OS+1]; +}hinfo_t; + +typedef struct _minfo +{ + u_char rmailbx[DNS_MAX_NAME+1]; + u_char emailbx[DNS_MAX_NAME+1]; +}minfo_t; + +typedef struct _mx +{ + u_int16_t preference; + u_char exchange[DNS_MAX_NAME+1]; +}mx_t; + +typedef struct _soa +{ + u_char mname[DNS_MAX_NAME+1]; + u_char rname[DNS_MAX_NAME+1]; + u_int32_t serial; + u_int32_t refresh; + u_int32_t retry; + u_int32_t expire; + u_int32_t minimum; +}soa_t; + +typedef struct txt_t +{ + u_char txt[DNS_MAX_NAME+1]; + u_char size; +}txt_t; + +typedef struct _null +{ + u_char null[DNS_MAX_NAME+1]; + u_char size; +}null_t; + +typedef struct _wks +{ + u_char protocol; + u_int32_t addr; + u_int32_t size; + u_char * bitmap; +}wks_t; + +typedef struct _srv +{ + u_int16_t priority; + u_int16_t weight; + u_int16_t port; + u_char target[DNS_MAX_TARGET]; +}srv_t; + +typedef struct _ds +{ + u_int16_t key_tag; + u_char algo; + u_char digest_type; + u_int32_t digest_len; + u_char *digest; +}ds_t; + + +typedef struct _rrsig +{ + u_int16_t type_covered; + u_char algo; + u_char labels; + u_int32_t original_ttl; + u_int32_t sig_expiration; + u_int32_t sig_inception; + u_int32_t key_tag; + u_int32_t signature_len; + u_char signer_name[DNS_MAX_SIGNER_NAME]; + u_char *signature; +}rrsig_t; + +typedef struct _nsec +{ + u_int16_t maps_len; + u_char next_domain[DNS_MAX_OWNER]; + u_char type_bit_maps[DNS_MAX_MAPS]; +}nsec_t; + +typedef struct _dnskey +{ + u_int16_t flags; + u_char protocol; + u_char algo; + u_int32_t public_key_len; + u_char *public_key; +}dnskey_t; + + +typedef struct _nsec3 +{ + u_char hash_algo; + u_char flags; + u_char salt_len; + u_char hash_len; + u_int16_t iteration; + u_int16_t maps_len; + u_char *salt_value; + u_char *next_hash_owner; + u_char type_bit_maps[DNS_MAX_MAPS]; +}nsec3_t; + +typedef struct _nsec3param +{ + u_char hash_algo; + u_char flags; + u_char salt_len; + u_int16_t iteration; + u_char *salt_value; +}nsec3param_t; + +typedef struct _dns_rr +{ + u_char name[DNS_MAX_NAME+1]; + u_int16_t type; + u_int16_t rr_class; + u_int32_t ttl; /* 1byte: extended RCODE; 1byte: version; 2bytes: Z(upper bit) if type is OPT */ + u_int16_t rdlength; + union + { + u_char *cname; /* cname[DNS_MAX_NAME + 1]; */ + hinfo_t *hinfo; + u_char *mb; /* mb[DNS_MAX_NAME + 1]; */ + u_char *md; /* md[DNS_MAX_NAME + 1]; */ + u_char *mf; /* mf[DNS_MAX_NAME + 1]; */ + u_char *mg; /* mg[DNS_MAX_NAME + 1]; */ + minfo_t *minfo; + u_char *mr; /* mr[DNS_MAX_NAME + 1]; */ + mx_t *mx; + u_char *ns; /* ns[DNS_MAX_NAME + 1]; */ + u_char *ptr; /* ptr[DNS_MAX_NAME + 1]; */ + soa_t *soa; + u_char *a; + u_char *aaaa; /* aaaa[16]; */ + u_char *dname; + u_char *isdn; + txt_t *txt; + null_t *null; + wks_t *wks; + srv_t *srv; + ds_t *ds; + rrsig_t *rrsig; + nsec_t *nsec; + dnskey_t *dnskey; + nsec3_t *nsec3; + nsec3param_t *nsec3param; + } rdata; +} dns_rr_t; + +typedef struct _fake_packet_opt +{ + u_int16_t cfg_type; /* IP or STR */ + u_int16_t res_type; + u_int32_t ttl; + u_int32_t res_len; + u_char res_info[DNS_MAX_NAME+1]; +}cheat_pkt_opt_t; + +typedef struct +{ + u_int16_t qtype; + u_int16_t qclass; + u_char qname[DNS_MAX_NAME+1]; +} dns_query_question_t; + +typedef struct _dns_info +{ + dns_hdr_t hdr_info; + int rr_count; + dns_rr_t *rr; + dns_query_question_t *query_question; +}dns_info_t; + + + +enum flag_id +{ + /* ������ֶ�ʱ�������Զ�����ͷ����Ϣ */ + DNS_UNKOWN =0, + DNS_ALL = 1<<0, /* ȫ�� */ + DNS_REQ_ALL = 1<<1, /* �����ȫ�� */ + DNS_RES_ALL = 1<<2, /* ���Ӧ���ȫ������ */ + DNS_REQ_HDR = 1<<3, /* �������ͷ������ */ + DNS_RES_HDR = 1<<4, /* ��Ӧ���ͷ������ */ + //DNS_REQ_QUERY = 1<<5, /* ��Ӧ����е�������Ϣ(������������ѯ��Ϣ���Զ�����ͷ������ΪDNS_REQ_ALL_FLAG_ID������û��Ҫ����һ��ֵ) */ + DNS_RES_QUERY = 1<<6, /* ��Ӧ����е�������Ϣ */ + DNS_RES_RRS = 1<<7, /* ������Ӧ����Դ��¼ */ + DNS_RES_ANSWER = 1<<8, /* ��answerӦ���¼ */ + DNS_RES_AUTH = 1<<9, /* ����Ȩ��Դ��¼ */ + DNS_RES_ADD = 1<<10, /* �⸽����Դ��¼ */ +}; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* +* name:build_dns_payload +* functionality:build dns packet +* param: +* pay_load_buf:the thread num +* len:buffer length +* pkt_para:option parameter +* opt_cnt:option counts +* +* returns: +* >0:build sucess +* -1:ibuild failed +* +* */ + +int get_rr_content2buf(dns_rr_t *rr, int rr_count, char *rr_buf, int buflen, int *dns_sec); +int dns_save_raw_pkt(char *buf, int buflen, const struct streaminfo * a_stream); +int build_cheat_pkt(unsigned char *payload, int payload_len, dns_query_question_t *query_question, cheat_pkt_opt_t *cheat_opt, int cheat_opt_num); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/dns_global.map b/src/dns_global.map new file mode 100644 index 0000000..8288e5b --- /dev/null +++ b/src/dns_global.map @@ -0,0 +1,11 @@ +{ +global: + build_dns_payload; + DNS_INIT; + DNS_DESTROY; + UDP_ENTRY; + PROT_FUNSTAT; + FLAG_CHANGE; + GET_PLUGID; +local:*; +}; diff --git a/src/dns_internal.h b/src/dns_internal.h new file mode 100644 index 0000000..114197f --- /dev/null +++ b/src/dns_internal.h @@ -0,0 +1,177 @@ +#ifndef DNS_ANALYSE_INTERNAL_H +#define DNS_ANALYSE_INTERNAL_H + +#include <MESA/stream.h> +//#include <MESA/MESA_handle_logger.h> +//#include <MESA/MESA_prof_load.h> +//#include "dfb_dns_config.h" +//#include "dns_analyse.h" + + +#ifndef MIN +#define MIN(a, b) ((a) > (b) ? (b) : (a)) +#endif + + +#define RUNTIME_DNSMODULE "[DNS MODULE:]" + +#define DNS_PORT 53 +#define PROTID_DNS 6 + +#define DNS_MAX_LABEL 63 + +#define MAX_FLAG_LEN 30 + +#define DNS_MAX_UDP_MESSAGE 512 + + +#define DNSHDR_OPCODE_QUERY 0 +#define DNSHDR_OPCODE_IQUERY 1 +#define DNSHDR_OPCODE_STATUS 2 + +#define DNSHDR_RCODE_NOERR 0 +#define DNSHDR_RCODE_FMTERR 1 +#define DNSHDR_RCODE_SRVFAIL 2 +#define DNSHDR_RCODE_NAMEERR 3 +#define DNSHDR_RCODE_NOTIMPL 4 +#define DNSHDR_RCODE_REFUSE 5 + +#define GET_TYPE_YD1 1 +#define GET_TYPE_YD2 2 +#define GET_TYPE_AUTH 3 +#define GET_TYPE_ADDIT 4 + +#define NS_INT16SZ 2 +#define NS_INT32SZ 4 + +#define DNS_RR_TYPE_ALL 0 +#define DNS_RR_TYPE_ANS 1 +#define DNS_RR_TYPE_AUTH 2 +#define DNS_RR_TYPE_ADD 3 + +#define DNS_ERROR_UNKNOWN 0 +#define DNS_ERROR_QUESTION 1 +#define DNS_ERROR_PAYLOAD_SHORT 2 +#define DNS_ERROR_CLASS_UNKNOWN 3 +#define DNS_ERROR_RR 4 +#define DNS_ERROR_ALL 5 + + + + +#define NS_GET32(l, cp) do { \ + register u_char *t_cp = (u_char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += NS_INT32SZ; \ +} while (0) + +#define NS_PUT16(s, cp) do { \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_PUT32(l, cp) do { \ + register u_int32_t t_l = (u_int32_t)(l); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += NS_INT32SZ; \ +} while (0) + +#define NS_GET16(s, cp) do { \ + register u_char *t_cp = (u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define SET_BIT(flag, bit) (flag&(~bit)) + + +/* 2015-09-07 lijia add, for get_plug_id() bug. */ +typedef struct +{ + const char *str; + unsigned long long id; +}dns_str_contrast_id_t; + + +typedef struct _save_dns_business_info +{ + void *business_pme; + int session_state; + +}save_dns_business_info_t; + +typedef struct _pcap_hdr +{ + u_int32_t tv_sec; + u_int32_t tv_usec; + u_int32_t len; + u_int32_t caplen; +}pcap_hdr_t; + +#define MAX_LOG_PATH_LEN 256 + +enum dns_statis_info_t +{ + V4_T_PPS=0, + V4_T_BPS, + V4_U_PPS, + V4_U_BPS, + V6_T_PPS, + V6_T_BPS, + V6_U_PPS, + V6_U_BPS, + PKT_UNKNOWN, + Q_PKT, + R_PKT, + ERR_PKT, + Q_A, + Q_AAAA, + Q_CNAME, + Q_UNKNOWN +}; + +#define DNS_MAX_FIELD_ID_NUM 32 + +typedef struct _dns_proto_info +{ + int log_level; + int cycle_time; + int fild_id[DNS_MAX_FIELD_ID_NUM]; + char log_path[MAX_LOG_PATH_LEN]; + + void *logger; + void *stat_handle; +}g_dns_proto_info_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +int get_rr_domain( char * msg,unsigned char ** ptr, unsigned char * buf, int buflen, char * end); +int DNS_INIT(); +void DNS_DESTROY(); +void PROT_FUNSTAT(long long protflag); +void GET_PLUGID(unsigned short plugid); +long long FLAG_CHANGE(char* raw_flag_str); +char DNS_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a_packet); +char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a_packet); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/test/bin/dns_test.inf b/test/bin/dns_test.inf new file mode 100644 index 0000000..ec817eb --- /dev/null +++ b/test/bin/dns_test.inf @@ -0,0 +1,9 @@ +[PLUGINFO] +PLUGNAME=DNS_TEST +SO_PATH=./plug/business/dns_test/dns_test.so +INIT_FUNC=dns_test_init +DESTROY_FUNC=dns_test_destory + +[DNS] +FUNC_FLAG=DNS_ALL +FUNC_NAME=dns_test_entry diff --git a/test/src/Makefile b/test/src/Makefile new file mode 100644 index 0000000..6f46816 --- /dev/null +++ b/test/src/Makefile @@ -0,0 +1,5 @@ +all: + gcc -Wall -g -fPIC -shared -I./include/ ./dns_test.c -o dns_test.so + cp ./dns_test.so ../bin/ +clean: + rm -rf *.o *.so diff --git a/test/src/dns_test.c b/test/src/dns_test.c new file mode 100644 index 0000000..915b10f --- /dev/null +++ b/test/src/dns_test.c @@ -0,0 +1,365 @@ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <arpa/inet.h> +#include <pcap/pcap.h> +#include <assert.h> + +#include <MESA/stream.h> +#include <MESA/dns_analyse.h> + +#define LOG_PATH "./log/dns/" +//#define DEBUG 1 + +int rr_print(dns_info_t *dns_info, struct streaminfo *a_udp, int thread_seq, void *a_packet, int *dns_sec) +{ + int i = 0, j = 0; + int used_len = 0, len = 0; + FILE *fp = NULL; + char filename[256]; + char dns_header[256]; + char question[1024]; + char rr_buf[4096]; + char ip_str[128]; + char tmp_buf[2048]; + char maps[2048]; + char salt_value[2048]; + dns_rr_t *dns_rr = NULL; + char *buf = NULL; + int buflen = sizeof(rr_buf); + buf = rr_buf; + + + memset(filename, 0 , sizeof(filename)); + memset(dns_header, 0 , sizeof(dns_header)); + snprintf(filename, sizeof(filename), "%s%s", (char *)LOG_PATH, printaddr(&a_udp->addr, thread_seq)); + + fp = fopen(filename, "a+"); + if(fp == NULL) + { + return 0; + } + + used_len = snprintf(dns_header, sizeof(dns_header), + "hdr_info: <id=0X%02x, QR=%d, OPCODE=%d, AA=%d, TC=%d, RD=%d, RA=%d,Z=%d, RCODE=%d, qdcount=%d, ancount=%d, aucount=%d, adcount=%d>\n", + dns_info->hdr_info.id, + dns_info->hdr_info.qr, + dns_info->hdr_info.opcode, + dns_info->hdr_info.aa, + dns_info->hdr_info.tc, + dns_info->hdr_info.rd, + dns_info->hdr_info.ra, + dns_info->hdr_info.z, + dns_info->hdr_info.rcode, + dns_info->hdr_info.qdcount, + dns_info->hdr_info.ancount, + dns_info->hdr_info.aucount, + dns_info->hdr_info.adcount); + + fwrite(dns_header, used_len, 1, fp); + + for(i = 0; i < dns_info->hdr_info.qdcount; i++) + { + used_len = snprintf(question, sizeof(question), "question: <qtype: %d, qclass: %d, qname: %s>\n", + dns_info->query_question[i].qtype, + dns_info->query_question[i].qclass, + dns_info->query_question[i].qname); + } + + fwrite(question, used_len, 1, fp); + + used_len = snprintf(rr_buf, sizeof(rr_buf), "RRS count: %d\n", dns_info->rr_count); + fwrite(rr_buf, used_len, 1, fp); + + for(i = 0; i < dns_info->rr_count; i++) + { + used_len = 0; + dns_rr = &(dns_info->rr[i]); + memset(rr_buf, 0 , sizeof(rr_buf)); + + if(dns_rr->type == DNS_TYPE_OPT) + { + used_len += snprintf(rr_buf, sizeof(rr_buf), "RRS%d OPT <name: %s, type: %d, udp_payload: %d, extended RCODE: %d, version: %d, Z; 0X%x, rdlength: %d>\n", + i, + dns_rr->name, + dns_rr->type, + dns_rr->rr_class, + dns_rr->ttl >> 24, + (dns_rr->ttl>>16)&0xFF, + dns_rr->ttl&&0xFFFF, + dns_rr->rdlength); + } + else + { + used_len += snprintf(rr_buf, sizeof(rr_buf), "RRS%d <name: %s, type: %d, rr_class: %d, ttl: %d, rdlength: %d>", + i, + dns_rr->name, + dns_rr->type, + dns_rr->rr_class, + dns_rr->ttl, + dns_rr->rdlength); + + } + + switch(dns_rr->type) + { + case DNS_TYPE_A: + inet_ntop(AF_INET, (void *)(dns_rr->rdata.a), ip_str, sizeof(ip_str)); + used_len += snprintf(buf+used_len, buflen-used_len, "[A: %s]\n", ip_str); + break; + case DNS_TYPE_NS: + used_len += snprintf(buf+used_len, buflen-used_len, "[NS: %s]\n", dns_rr->rdata.ns); + break; + case DNS_TYPE_MD: + used_len += snprintf(buf+used_len, buflen-used_len, "[MD: %s]\n", dns_rr->rdata.md); + break; + case DNS_TYPE_MF: + used_len += snprintf(buf+used_len, buflen-used_len, "[MF: %s]\n", dns_rr->rdata.mf); + break; + case DNS_TYPE_CNAME: + used_len += snprintf(buf+used_len, buflen-used_len, "[CNAME: %s]\n", dns_rr->rdata.cname); + break; + case DNS_TYPE_SOA: + used_len += snprintf(buf+used_len, buflen-used_len, + "[SOA mname: %s, rname: %s, serial: %u, refresh: %u, retry: %u, expire: %u, minimum: %u]\n", + dns_rr->rdata.soa->mname, + dns_rr->rdata.soa->rname, + dns_rr->rdata.soa->serial, + dns_rr->rdata.soa->refresh, + dns_rr->rdata.soa->retry, + dns_rr->rdata.soa->expire, + dns_rr->rdata.soa->minimum); + break; + case DNS_TYPE_MB: + used_len += snprintf(buf+used_len, buflen-used_len, "[MB: %s]\n", dns_rr->rdata.mb); + break; + case DNS_TYPE_MG: + used_len += snprintf(buf+used_len, buflen-used_len, "[MG: %s]\n", dns_rr->rdata.mg); + break; + case DNS_TYPE_MR: + used_len += snprintf(buf+used_len, buflen-used_len, "[MR: %s]\n", dns_rr->rdata.mr); + break; + case DNS_TYPE_NULL: + used_len += snprintf(buf+used_len, buflen-used_len, "[null size: %u, null: %s]\n", + dns_rr->rdata.null->size, dns_rr->rdata.null->null); + break; + case DNS_TYPE_WKS: + inet_ntop(AF_INET, &(dns_rr->rdata.wks->addr), ip_str, sizeof(ip_str)); + used_len += snprintf(buf+used_len, buflen-used_len, "[WKS addr: %s, protocol: %u, bitmap: %s, size: %u]\n", + ip_str, dns_rr->rdata.wks->protocol, dns_rr->rdata.wks->bitmap, dns_rr->rdata.wks->size); + break; + case DNS_TYPE_PTR: + used_len += snprintf(buf+used_len, buflen-used_len, "[PTR: %s]\n", dns_rr->rdata.ptr); + break; + case DNS_TYPE_HINFO: + used_len += snprintf(buf+used_len, buflen-used_len, "[HINFO cpu: %s, os: %s]\n", + dns_rr->rdata.hinfo->cpu, dns_rr->rdata.hinfo->os); + break; + case DNS_TYPE_MINFO: + used_len += snprintf(buf+used_len, buflen-used_len, "[MINFO rmailbx: %s, emailbx: %s]\n", + dns_rr->rdata.minfo->rmailbx, dns_rr->rdata.minfo->emailbx); + break; + case DNS_TYPE_MX: + used_len += snprintf(buf+used_len, buflen-used_len, "[MX preference: %u, exchange: %s]\n", + dns_rr->rdata.mx->preference, dns_rr->rdata.mx->exchange); + break; + case DNS_TYPE_TXT: + used_len += snprintf(buf+used_len, buflen-used_len, "[TXT size: %u, txt: %s]\n", + dns_rr->rdata.txt->size, dns_rr->rdata.txt->txt); + break; + case DNS_TYPE_AAAA: + inet_ntop(AF_INET6, dns_rr->rdata.aaaa, ip_str, sizeof(ip_str)); + used_len += snprintf(buf+used_len, buflen-used_len, "[AAAA: %s]\n", ip_str); + break; + case DNS_TYPE_OPT: + break; + case DNS_TYPE_DS: + *dns_sec = 2; + len = 0; + assert(dns_rr->rdata.ds->digest_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.ds->digest_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.ds->digest[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, + "[DS key_tag: %u, algo: %u, digest_type: %u, digest: %s]\n", + dns_rr->rdata.ds->key_tag, dns_rr->rdata.ds->algo, + dns_rr->rdata.ds->digest_type, tmp_buf); + break; + case DNS_TYPE_RRSIG: + *dns_sec = 2; + len = 0; + assert(dns_rr->rdata.rrsig->signature_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.rrsig->signature_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.rrsig->signature[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, + "[RRSIG type_covered: %u, algo: %u, labels: %u, original_ttl: %u, sig_expiration: %u, sig_inception: %u, key_tag: %u, signer_name: %s, signature: %s]\n", + dns_rr->rdata.rrsig->type_covered, dns_rr->rdata.rrsig->algo, + dns_rr->rdata.rrsig->labels, dns_rr->rdata.rrsig->original_ttl, + dns_rr->rdata.rrsig->sig_expiration, dns_rr->rdata.rrsig->sig_inception, + dns_rr->rdata.rrsig->key_tag, dns_rr->rdata.rrsig->signer_name, tmp_buf); + break; + case DNS_TYPE_NSEC: + *dns_sec = 2; + len = 0; + for(j = 0; j < (int)(dns_rr->rdata.nsec->maps_len); j++) + { + len += snprintf(maps+len, sizeof(maps)-len, "%02x", dns_rr->rdata.nsec->type_bit_maps[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, "[NSEC next_domain: %s, type_bit_maps: %s]\n", dns_rr->rdata.nsec->next_domain, maps); + break; + case DNS_TYPE_DNSKEY: + *dns_sec = 2; + len = 0; + assert(dns_rr->rdata.dnskey->public_key_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.dnskey->public_key_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.dnskey->public_key[j]); + } + used_len += snprintf(buf+used_len, buflen-used_len, "[DNSKEY flags: %u, protocol: %u, algo: %u, public_key: %s]\n", + dns_rr->rdata.dnskey->flags, dns_rr->rdata.dnskey->protocol, dns_rr->rdata.dnskey->algo, tmp_buf); + break; + case DNS_TYPE_NSEC3: + *dns_sec = 2; + memset(tmp_buf, 0, sizeof(tmp_buf)); + memset(maps, 0, sizeof(maps)); + len = 0; + assert(dns_rr->rdata.nsec3->hash_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.nsec3->hash_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.nsec3->next_hash_owner[j]); + } + len = 0; + for(j = 0; j < (int)(dns_rr->rdata.nsec3->maps_len); j++) + { + len += snprintf(maps+len, sizeof(maps)-len, "%02x", dns_rr->rdata.nsec3->type_bit_maps[j]); + } + len = 0; + for(j = 0; j < (int)(dns_rr->rdata.nsec3->salt_len); j++) + { + len += snprintf(salt_value+len, sizeof(salt_value)-len, "%02x", dns_rr->rdata.nsec3->salt_value[j]); + } + + used_len += snprintf(buf+used_len, buflen-used_len, + "[NSEC3 hash_algo: %u, flags: %u, iteration: %u, salt_len: %u, hash_len: %u, salt_value: %s, next_hash_owner: %s, type_bit_maps: %s]\n", + dns_rr->rdata.nsec3->hash_algo, dns_rr->rdata.nsec3->flags, + dns_rr->rdata.nsec3->iteration, dns_rr->rdata.nsec3->salt_len, + dns_rr->rdata.nsec3->hash_len, salt_value, tmp_buf, maps); + break; + case DNS_TYPE_NSEC3PARAM: + len = 0; + assert(dns_rr->rdata.nsec3param->salt_len*2<sizeof(tmp_buf)); + for(j = 0; j < (int)(dns_rr->rdata.nsec3param->salt_len); j++) + { + len += snprintf(tmp_buf+len, sizeof(tmp_buf)-len, "%02x", dns_rr->rdata.nsec3param->salt_value[j]); + } + + used_len += snprintf(buf+used_len, buflen-used_len, + "[NSEC3PARAM hash_algo: %u, flags: %u, iteration: %u, salt_len: %u, salt_value: %s]\n", + dns_rr->rdata.nsec3param->hash_algo, dns_rr->rdata.nsec3param->flags, + dns_rr->rdata.nsec3param->iteration, dns_rr->rdata.nsec3param->salt_len, + tmp_buf); + break; + case DNS_QTYPE_AXFR: + continue; + break; + case DNS_QTYPE_MAILB: + continue; + break; + case DNS_QTYPE_MAILA: + continue; + break; + case DNS_QTYPE_ANY: + continue; + break; + default: + continue; + break; + } + fwrite(buf, used_len, 1, fp); + } + + fclose(fp); + fp = NULL; + + return 0; +} + +char dns_test_entry (stSessionInfo *session_info, void **pme, int thread_seq, struct streaminfo *a_udp, void *a_packet) +{ + int dns_sec = 0; + dns_info_t *dns_info = (dns_info_t *)session_info->app_info; + + if(dns_info!= NULL) + { + #ifdef DEBUG + rr_print(dns_info, a_udp, thread_seq, a_packet, &dns_sec); + #endif + } + + return PROT_STATE_GIVEME; +} + + +char dns_build_cheat_pkt_entry (stSessionInfo *session_info, void **pme, int thread_seq, struct streaminfo *a_udp, void *a_packet) +{ + unsigned char payload[4096] = {0}; + int payload_len = sizeof(payload); + cheat_pkt_opt_t cheat_opt; + int cheat_opt_num = 0; + unsigned char senddir = 0; + char *cheat_ipv6 = "11:22:33:44:55::66"; + + dns_hdr_t *dns_hdr = NULL; + + + + dns_info_t *dns_info = (dns_info_t *)session_info->app_info; + + memset(payload, 0, payload_len); + dns_hdr = (dns_hdr_t *)payload; + + if(dns_info!= NULL) + { + switch(dns_info->query_question->qtype) + { + case DNS_TYPE_A: + cheat_opt.res_type = DNS_TYPE_A; + cheat_opt.res_len = 4; + *(unsigned int *)cheat_opt.res_info = 3825598474; + cheat_opt_num = 1; + dns_hdr->ancount = 1; + dns_hdr->id = dns_info->hdr_info.id; + dns_hdr->qdcount = 1; + break; + case DNS_TYPE_AAAA: + cheat_opt.res_type = DNS_TYPE_AAAA; + cheat_opt.res_len = 16; + inet_pton(AF_INET6, cheat_ipv6, cheat_opt.res_info); + cheat_opt_num = 1; + dns_hdr->ancount = 1; + dns_hdr->id = dns_info->hdr_info.id; + dns_hdr->qdcount = 1; + break; + } + payload_len = build_cheat_pkt(payload, payload_len, dns_info->query_question, &cheat_opt, cheat_opt_num); + senddir = (a_udp->routedir)^1; + MESA_inject_pkt(a_udp, (const char *)payload, payload_len, (const char *)a_packet, senddir); + } + + return PROT_STATE_DROPME; +} + +int dns_test_init() +{ + + return 0; +} + +void dns_test_destory() +{ + +} + |
