#include #include #include #include #include #include "../src/pub.h" #include "../src/dns.h" #define ERROR(str) \ { \ printf(str); \ exit(1); \ } typedef struct { int len; const char *data; } str_t; typedef struct { const char *desc; str_t req; str_t rsp; } package_t; static package_t package_arry[] = { { "dig @127.0.0.1 www.baidu.com a", {56, "TDwBIAABAAAAAAABA3d3dwViYWlkdQNjb20AAAEAAQAAKRAAAAAAAAAA"}, {136, "TDyBgAABAAMAAAABA3d3dwViYWlkdQNjb20AAAEAAcAMAAUAAQAAACoADwN3d3cBYQZzaGlmZW7AFsArAAEAAQAAACoABLY9yAfAKwABAAEAAAAqAAS2PcgGAAApEAAAAAAAAAA="}, }, { "dig @127.0.0.1 baidu.com ns", {52, "M00BIAABAAAAAAABBWJhaWR1A2NvbQAAAgABAAApEAAAAAAAAAA="}, {172, "M02BgAABAAUAAAABBWJhaWR1A2NvbQAAAgABwAwAAgABAAAcJwAGA25zNMAMwAwAAgABAAAcJwAGA25zMsAMwAwAAgABAAAcJwAGA25zN8AMwAwAAgABAAAcJwAGA2Ruc8AMwAwAAgABAAAcJwAGA25zM8AMAAApEAAAAAAAAAA="}, }, { "dig @127.0.0.1 www.baidu.com cname", {56, "LAMBIAABAAAAAAABA3d3dwViYWlkdQNjb20AAAUAAQAAKRAAAAAAAAAA"}, {92, "LAOBgAABAAEAAAABA3d3dwViYWlkdQNjb20AAAUAAcAMAAUAAQAAAGYADwN3d3cBYQZzaGlmZW7AFgAAKRAAAAAAAAAA"}, }, { "dig @127.0.0.1 www.baidu.com soa", {56, "9D8BIAABAAAAAAABA3d3dwViYWlkdQNjb20AAAYAAQAAKRAAAAAAAAAA"}, {168, "9D+BgAABAAEAAQABA3d3dwViYWlkdQNjb20AAAYAAcAMAAUAAQAAAhcADwN3d3cBYQZzaGlmZW7AFsAvAAYAAQAAAmIALQNuczHALxBiYWlkdV9kbnNfbWFzdGVywBB3hAIjAAAABQAAAAUAJ40AAAAOEAAAKRAAAAAAAAAA"}, }, { "dig @127.0.0.1 -x 192.30.252.153", {76, "G+4BIAABAAAAAAABAzE1MwMyNTICMzADMTkyB2luLWFkZHIEYXJwYQAADAABAAApEAAAAAAAAAA="}, {136, "G+6BgAABAAEAAAABAzE1MwMyNTICMzADMTkyB2luLWFkZHIEYXJwYQAADAABwAwADAABAAAOEAAiFWxiLTE5Mi0zMC0yNTItMTUzLWlhZAZnaXRodWIDY29tAAAAKRAAAAAAAAAA"}, }, { "dig @127.0.0.1 163.com mx", {48, "iRMBIAABAAAAAAABAzE2MwNjb20AAA8AAQAAKRAAAAAAAAAA"}, {196, "iROBgAABAAQAAAABAzE2MwNjb20AAA8AAcAMAA8AAQAADnQAGwAKBzE2M214MDEGbXhtYWlsB25ldGVhc2XAEMAMAA8AAQAADnQADAAyBzE2M214MDDAL8AMAA8AAQAADnQADAAKBzE2M214MDPAL8AMAA8AAQAADnQADAAKBzE2M214MDLALwAAKRAAAAAAAAAA"}, }, { "dig @127.0.0.1 baidu.com txt", {52, "A6kBIAABAAAAAAABBWJhaWR1A2NvbQAAEAABAAApEAAAAAAAAAA="}, {296, "A6mBgAABAAIAAAABBWJhaWR1A2NvbQAAEAABwAwAEAABAAAIKgBFRGdvb2dsZS1zaXRlLXZlcmlmaWNhdGlvbj1HSGI5OC02bXNxeXhfcXFqR2w1ZVJhdEQzUVRIeVZCNi14UTNnSkI1VXdNwAwAEAABAAAIKgBaWXY9c3BmMSBpbmNsdWRlOnNwZjEuYmFpZHUuY29tIGluY2x1ZGU6c3BmMi5iYWlkdS5jb20gaW5jbHVkZTpzcGYzLmJhaWR1LmNvbSBhIG14IHB0ciAtYWxsAAApEAAAAAAAAAA="}, }, { "dig @127.0.0.1 www.taobao.com aaaa", {60, "0qQBIAABAAAAAAABA3d3dwZ0YW9iYW8DY29tAAAcAAEAACkQAAAAAAAAAA=="}, {640, "0qSBgAABAA8AAAABA3d3dwZ0YW9iYW8DY29tAAAcAAHADAAFAAEAAAG2ACEDd3d3BnRhb2JhbwNjb20HZGFudW95aQd0YmNhY2hlwBfALAAcAAEAAAA8ABAkDgCxmAEEAAADAAAAAAP5wCwAHAABAAAAPAAQJA4AsZgBBAkAAwAAAAAD+cAsABwAAQAAADwAECQOALGYAQQAAAMAAAAAA/rALAAcAAEAAAA8ABAkDglA4AEAAQADAAAAAAP5wCwAHAABAAAAPAAQJA4AsZgBBAgAAwAAAAAD+sAsABwAAQAAADwAECQOCUDgAQABAAMAAAAAA/rALAAcAAEAAAA8ABAkDglA4AEABQADAAAAAAP5wCwAHAABAAAAPAAQJA4AsaggAAAAAwAAAAAD9cAsABwAAQAAADwAECQOALGoIAAAAAMAAAAAA/bALAAcAAEAAAA8ABAkDgCxmAEECQADAAAAAAP6wCwAHAABAAAAPAAQJA4JQOABAAQAAwAAAAAD+cAsABwAAQAAADwAECQOCUDgAQAEAAMAAAAAA/rALAAcAAEAAAA8ABAkDgCxmAEECAADAAAAAAP5wCwAHAABAAAAPAAQJA4JQOABAAUAAwAAAAAD+gAAKRAAAAAAAAAA"}, }, { "dig @127.0.0.1 com ds", {44, "94UBIAABAAAAAAABA2NvbQAAKwABAAApEAAAAAAAAAA="}, {108, "94WBgAABAAEAAAABA2NvbQAAKwABwAwAKwABAAB/zgAkeL0IAuLTyRb23urHMpToJo+1iFBEqDP8VFlYj0qRhM/EGldmAAApEAAAAAAAAAA="}, }, { "dig @127.0.0.1 com rrsig", {44, "ETMBIAABAAAAAAABA2NvbQAALgABAAApEAAAAAAAAAA="}, {948, "ETOBgAABAAMAAAABA2NvbQAALgABwAwALgABAAABjgC3AAYIAQAAA4RexfcOXrysJpukA2NvbQAJCiOw6MPHup5mJVrn65fULwvBJoy5mR1IYTJSEzv7PXsT+B/3lp+5Gnfds89MvligsnUWkQvOUiCOkY5ahPwO5fQSB4dDPZJXahG44IR2QtNDHLfFNxcRROwdLmmSe9F+sU5ZL4YtmXu4+trwUycbo34f19o3xRS5D6UBV1clWPp0yK9rQafhMY5UBIZz83txHKumVVjwlnsA2d7w1Qi7wDMALgABAAEBrwETACsIAQABUYBezYNQXrxRwL8HAF4VVK323NSvS//r44sD6QQDSa9aNBCPlimQWZUbjmAh2Z/RkwTAuK0T3ngOw5flW8rHaopbNfIQ4UZSNqzcbzXtJ/F2u2DG4/Xo26LRbF1jHBZOGChGMeug4kVVepPuQvxEoSBUY9FgdGXMZ551kxO/xf3kK6xMhmjQjOQn1xJzZEGtcqV+5pKymT4MNdfPdhpJIDQRnN33bvk8su7wPiaJmGsKGdGHBKlsyMJgLCoJrMvSQIEiQj560Rwy1n1qq3Mlk6CkydQ62mZp2u32d4wBTE3UTs+aDBRfTSQmg6Dofh9x2DJgK5mFISt7rYgvacxpRfqBkD4tDdKUQlrszbjAMwAuAAEAAk6gALcAAggBAAKjAF7AwkJet3dam6QDY29tAJK2SHQgAOJ0UOxt+9f55rJHx5vzvSuuuTsaM06kaK8zhK6Xo0IRqWtu12EHehn3UiPoTGEdUK/KK2ZXmdb8yJ/H+L4BRG9AafN7xaHPAf4GbXr0pV4yOl+HoTEstZmL3JgXHPFMRLl66UYbNGBDFE6B1f1MNZlBvk6c3NjeMSN29DOIZRoajZlDKv3IRhOrRJghwLr5vhlODIwm58lTbI0AACkQAAAAAAAAAA=="}, }, { "dig @127.0.0.1 com dnskey", {44, "FJwBIAABAAAAAAABA2NvbQAAMAABAAApEAAAAAAAAAA="}, {648, "FJyBgAABAAIAAAABA2NvbQAAMAABwAwAMAABAAAL5wEGAQEDCAEDw85XTZjL2RV+DXDSdLhJyg4O7Zr/xdzMkEdJaQZlXDXLCLM8TRcbAXyjVvSWAmKqYpPN+uixO1WyHDUc36dofTjvB0Zfh/hNPM2rivJO3r1hJrv+qHftm6IID6IhHxjcrzT2kiOxTiK6A7J8P7WoIMx0V9We0jojoj1jzSMElMljme/VZnENRi5AujZWLxtx8GJsp0L+qBcBr/yhC0sO2Una200NB172W6jFCOwWjLJJr4JtRu6CmdWIhezvYqFTXNPuwEm6pmTe2ffBBlP0IdivwYFHvB7NF1XHTyq7cmJ6EB3dspyj3DDJUxIodv9hwx40TydmssCKSjZ7+KD6P8AMADAAAQAAC+cAqAEAAwgDAQABtsVzV+OQEJLJyG3tqH155FqW2csMraxXKjGSMLrMHOb/lIaB8Mb8fpcS6lPty2AK+ep7FqKdMh9ryecFgI60B5zsZ3W9voT/dJeSCINoxQleZ23wTuhu1VmqMWU3ZA2dOWN8yIQKfXqtleW9ciLbnlPXAWRa2nn4tQKK5+wtN4pz3FtDDvLS5yxH4YrPjIRK1tiL3x+cHmc7PNaFFRyV/QAAKRAAAAAAAAAA"}, }, { "dig @127.0.0.1 com nsec3param", {44, "s48BIAABAAAAAAABA2NvbQAAMwABAAApEAAAAAAAAAA="}, {68, "s4+BgAABAAEAAAABA2NvbQAAMwABwAwAMwABAABFmwAFAQAAAAAAACkQAAAAAAAAAA=="}, }, { "dig @127.0.0.1 _sip._udp.sip.voice.google.com srv", {80, "9OoBIAABAAAAAAABBF9zaXAEX3VkcANzaXAFdm9pY2UGZ29vZ2xlA2NvbQAAIQABAAApEAAAAAAAAAA="}, {212, "9OqBgAABAAIAAAABBF9zaXAEX3VkcANzaXAFdm9pY2UGZ29vZ2xlA2NvbQAAIQABwAwAIQABAAAAxAAmAAoAARPEDXNpcC1hbnljYXN0LTEFdm9pY2UGZ29vZ2xlA2NvbQDADAAhAAEAAADEACYAFAABE8QNc2lwLWFueWNhc3QtMgV2b2ljZQZnb29nbGUDY29tAAAAKRAAAAAAAAAA"}, }, { "dig @127.0.0.1 . nsec", {40, "3HUBIAABAAAAAAABAAAvAAEAACkQAAAAAAAAAA=="}, {72, "3HWBgAABAAEAAAABAAAvAAEAAC8AAQABUSUADgNhYWEAAAciAAAAAAOAAAApEAAAAAAAAAA="}, }}; static int package_arry_size = sizeof(package_arry) / sizeof(package_t); static int dns_print(dns_info_t *dns_info, const char *filename) { int i = 0, j = 0; int used_len = 0, len = 0; FILE *fp = NULL; 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; cJSON *dns_info_object = cJSON_CreateObject(); cJSON *dns_hdr_object = cJSON_CreateObject(); cJSON *dns_flags_object = cJSON_CreateObject(); cJSON *dns_question_array = cJSON_CreateArray(); cJSON *dns_rr_array = cJSON_CreateArray(); memset(dns_header, 0, sizeof(dns_header)); fp = fopen(filename, "a+"); if (fp == NULL) { return 0; } used_len = snprintf(dns_header, sizeof(dns_header), "hdr_info: \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); cJSON_AddNumberToObject(dns_hdr_object, "id", dns_info->hdr_info.id); cJSON_AddNumberToObject(dns_hdr_object, "qdcount", dns_info->hdr_info.qdcount); cJSON_AddNumberToObject(dns_hdr_object, "ancount", dns_info->hdr_info.ancount); cJSON_AddNumberToObject(dns_hdr_object, "aucount", dns_info->hdr_info.aucount); cJSON_AddNumberToObject(dns_hdr_object, "adcount", dns_info->hdr_info.adcount); cJSON_AddNumberToObject(dns_flags_object, "qr", dns_info->hdr_info.qr); cJSON_AddNumberToObject(dns_flags_object, "opcode", dns_info->hdr_info.opcode); cJSON_AddNumberToObject(dns_flags_object, "aa", dns_info->hdr_info.aa); cJSON_AddNumberToObject(dns_flags_object, "tc", dns_info->hdr_info.tc); cJSON_AddNumberToObject(dns_flags_object, "rd", dns_info->hdr_info.rd); cJSON_AddNumberToObject(dns_flags_object, "ra", dns_info->hdr_info.ra); cJSON_AddNumberToObject(dns_flags_object, "z", dns_info->hdr_info.z); cJSON_AddNumberToObject(dns_flags_object, "rcode", dns_info->hdr_info.rcode); fwrite(dns_header, used_len, 1, fp); cJSON_AddItemToObject(dns_info_object, "hdr", dns_hdr_object); cJSON_AddItemToObject(dns_info_object, "flags", dns_flags_object); cJSON_AddItemToObject(dns_info_object, "question", dns_question_array); used_len = snprintf(question, sizeof(question), "question: \n", dns_info->query_question.qtype, dns_info->query_question.qclass, dns_info->query_question.qname); cJSON *dns_question_object = cJSON_CreateObject(); cJSON_AddItemToArray(dns_question_array, dns_question_object); cJSON_AddNumberToObject(dns_question_object, "qtype", dns_info->query_question.qtype); cJSON_AddNumberToObject(dns_question_object, "qclass", dns_info->query_question.qclass); cJSON_AddStringToObject(dns_question_object, "qname", (const char *)dns_info->query_question.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); cJSON_AddItemToObject(dns_info_object, "rr", dns_rr_array); for (i = 0; i < dns_info->rr_count; i++) { cJSON *dns_rr_object = cJSON_CreateObject(); cJSON_AddItemToArray(dns_rr_array, dns_rr_object); 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 \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); cJSON_AddStringToObject(dns_rr_object, "name", (const char *)(dns_rr->name)); cJSON_AddNumberToObject(dns_rr_object, "type", dns_rr->type); cJSON_AddNumberToObject(dns_rr_object, "udp_payload", dns_rr->rr_class); cJSON_AddNumberToObject(dns_rr_object, "rcode", (int)(dns_rr->ttl >> 24)); cJSON_AddNumberToObject(dns_rr_object, "version", (int)((dns_rr->ttl >> 16) & 0xFF)); cJSON_AddNumberToObject(dns_rr_object, "Z", (int)(dns_rr->ttl && 0xFFFF)); cJSON_AddNumberToObject(dns_rr_object, "rdlength", dns_rr->rdlength); } else { used_len += snprintf(rr_buf, sizeof(rr_buf), "RRS%d ", i, dns_rr->name, dns_rr->type, dns_rr->rr_class, dns_rr->ttl, dns_rr->rdlength); cJSON_AddStringToObject(dns_rr_object, "name", (const char *)(dns_rr->name)); cJSON_AddNumberToObject(dns_rr_object, "type", dns_rr->type); cJSON_AddNumberToObject(dns_rr_object, "class", dns_rr->rr_class); cJSON_AddNumberToObject(dns_rr_object, "ttl", dns_rr->ttl); cJSON_AddNumberToObject(dns_rr_object, "rdlength", 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); cJSON_AddStringToObject(dns_rr_object, "a", ip_str); break; case DNS_TYPE_NS: used_len += snprintf(buf + used_len, buflen - used_len, "[NS: %s]\n", dns_rr->rdata.ns); cJSON_AddStringToObject(dns_rr_object, "ns", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "md", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "mf", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "cname", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "mname", (const char *)(dns_rr->rdata.soa.mname)); cJSON_AddStringToObject(dns_rr_object, "rname", (const char *)(dns_rr->rdata.soa.rname)); cJSON_AddNumberToObject(dns_rr_object, "serial", dns_rr->rdata.soa.serial); cJSON_AddNumberToObject(dns_rr_object, "refresh", dns_rr->rdata.soa.refresh); cJSON_AddNumberToObject(dns_rr_object, "retry", dns_rr->rdata.soa.retry); cJSON_AddNumberToObject(dns_rr_object, "cname", dns_rr->rdata.soa.expire); cJSON_AddNumberToObject(dns_rr_object, "minimum", 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); cJSON_AddStringToObject(dns_rr_object, "mb", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "mg", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "mr", (const char *)(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); cJSON_AddNumberToObject(dns_rr_object, "size", dns_rr->rdata.null.size); cJSON_AddStringToObject(dns_rr_object, "null", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "addr", ip_str); cJSON_AddNumberToObject(dns_rr_object, "protocol", dns_rr->rdata.wks.protocol); cJSON_AddStringToObject(dns_rr_object, "bitmap", (const char *)(dns_rr->rdata.wks.bitmap)); cJSON_AddNumberToObject(dns_rr_object, "size", 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); cJSON_AddStringToObject(dns_rr_object, "ptr", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "cpu", (const char *)(dns_rr->rdata.hinfo.cpu)); cJSON_AddStringToObject(dns_rr_object, "os", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "rmailbx", (const char *)(dns_rr->rdata.minfo.rmailbx)); cJSON_AddStringToObject(dns_rr_object, "emailbx", (const char *)(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); cJSON_AddStringToObject(dns_rr_object, "exchange", (const char *)(dns_rr->rdata.mx.exchange)); cJSON_AddNumberToObject(dns_rr_object, "preference", dns_rr->rdata.mx.preference); 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); cJSON_AddStringToObject(dns_rr_object, "txt", (const char *)(dns_rr->rdata.txt.txt)); cJSON_AddNumberToObject(dns_rr_object, "size", dns_rr->rdata.txt.size); break; case DNS_TYPE_RP: used_len += snprintf(buf + used_len, buflen - used_len, "[mailbox: %s, txt_rr: %s]\n", dns_rr->rdata.rp.mailbox, dns_rr->rdata.rp.txt_rr); cJSON_AddStringToObject(dns_rr_object, "mailbox", (const char *)(dns_rr->rdata.rp.mailbox)); cJSON_AddStringToObject(dns_rr_object, "txt_rr", (const char *)(dns_rr->rdata.rp.txt_rr)); 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); cJSON_AddStringToObject(dns_rr_object, "aaaa", ip_str); break; case DNS_TYPE_OPT: break; case DNS_TYPE_DS: 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); cJSON_AddNumberToObject(dns_rr_object, "key_tag", dns_rr->rdata.ds.key_tag); cJSON_AddNumberToObject(dns_rr_object, "algo", dns_rr->rdata.ds.algo); cJSON_AddNumberToObject(dns_rr_object, "digest_type", dns_rr->rdata.ds.digest_type); cJSON_AddStringToObject(dns_rr_object, "digest", tmp_buf); break; case DNS_TYPE_RRSIG: 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); cJSON_AddNumberToObject(dns_rr_object, "type_covered", dns_rr->rdata.rrsig.type_covered); cJSON_AddNumberToObject(dns_rr_object, "algo", dns_rr->rdata.rrsig.algo); cJSON_AddNumberToObject(dns_rr_object, "labels", dns_rr->rdata.rrsig.labels); cJSON_AddNumberToObject(dns_rr_object, "original_ttl", dns_rr->rdata.rrsig.original_ttl); cJSON_AddNumberToObject(dns_rr_object, "sig_expiration", dns_rr->rdata.rrsig.sig_expiration); cJSON_AddNumberToObject(dns_rr_object, "sig_inception", dns_rr->rdata.rrsig.sig_inception); cJSON_AddNumberToObject(dns_rr_object, "key_tag", dns_rr->rdata.rrsig.key_tag); cJSON_AddStringToObject(dns_rr_object, "signer_name", (const char *)(dns_rr->rdata.rrsig.signer_name)); cJSON_AddStringToObject(dns_rr_object, "signature", tmp_buf); break; case DNS_TYPE_NSEC: 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); cJSON_AddStringToObject(dns_rr_object, "next_domain", (const char *)(dns_rr->rdata.nsec.next_domain)); cJSON_AddStringToObject(dns_rr_object, "type_bit_maps", maps); break; case DNS_TYPE_DNSKEY: 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); cJSON_AddNumberToObject(dns_rr_object, "flags", dns_rr->rdata.dnskey.flags); cJSON_AddNumberToObject(dns_rr_object, "protocol", dns_rr->rdata.dnskey.protocol); cJSON_AddNumberToObject(dns_rr_object, "algo", dns_rr->rdata.dnskey.algo); cJSON_AddStringToObject(dns_rr_object, "public_key", tmp_buf); break; case DNS_TYPE_NSEC3: 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); cJSON_AddNumberToObject(dns_rr_object, "hash_algo", dns_rr->rdata.nsec3.hash_algo); cJSON_AddNumberToObject(dns_rr_object, "flags", dns_rr->rdata.nsec3.flags); cJSON_AddNumberToObject(dns_rr_object, "iteration", dns_rr->rdata.nsec3.iteration); cJSON_AddNumberToObject(dns_rr_object, "salt_len", dns_rr->rdata.nsec3.salt_len); cJSON_AddNumberToObject(dns_rr_object, "hash_len", dns_rr->rdata.nsec3.hash_len); cJSON_AddStringToObject(dns_rr_object, "salt_value", salt_value); cJSON_AddStringToObject(dns_rr_object, "next_hash_owner", tmp_buf); cJSON_AddStringToObject(dns_rr_object, "type_bit_maps", 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); cJSON_AddNumberToObject(dns_rr_object, "hash_algo", dns_rr->rdata.nsec3param.hash_algo); cJSON_AddNumberToObject(dns_rr_object, "flags", dns_rr->rdata.nsec3param.flags); cJSON_AddNumberToObject(dns_rr_object, "iteration", dns_rr->rdata.nsec3param.iteration); cJSON_AddNumberToObject(dns_rr_object, "salt_len", dns_rr->rdata.nsec3param.salt_len); cJSON_AddStringToObject(dns_rr_object, "salt_value", tmp_buf); break; case DNS_TYPE_UNKNOWN: used_len += snprintf(buf + used_len, buflen - used_len, "[data: %s]\n", dns_rr->rdata.unknown_data); cJSON_AddStringToObject(dns_rr_object, "data", (const char *)(dns_rr->rdata.unknown_data)); 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; //char *question_array=cJSON_Print(dns_info_object); //char *rr_array=cJSON_Print(dns_info_object); //cJSON_AddArrayToObject(dns_info_object, question_array); //cJSON_AddArrayToObject(dns_info_object, rr_array); char *outout1 = cJSON_PrintUnformatted(dns_info_object); char *outout2 = cJSON_Print(dns_info_object); printf("%s\n", outout1); printf("%s\n", outout2); free(outout1); free(outout2); cJSON_Delete(dns_info_object); return 0; } static void util_dump_dns(const char *data, int len, int is_req) { int en_len; int de_len; int out_len; char en_buff[102400] = {0}; char de_buff[102400] = {0}; char out_buff[102400 * 2] = {0}; en_len = base64_encode(en_buff, sizeof(en_buff), data, len); if (en_len == MS_ERROR) { ERROR("base64_encode() failed\n"); } de_len = base64_decode(de_buff, sizeof(de_buff), en_buff, en_len); if (de_len == MS_ERROR) { ERROR("base64_encode() failed\n"); } if (de_len != len || strncmp(data, de_buff, de_len) != 0) { ERROR("base64_encode() != base64_decode()\n"); } FILE *fp = fopen("dns_test_base64.log", "a+"); if (fp == NULL) { ERROR("fopen() failed\n"); } out_len = snprintf(out_buff, sizeof(out_buff), "dir:%s len:%04d, data:%s\n", is_req ? "req" : "rsp", en_len, en_buff); printf("%s", out_buff); fwrite(out_buff, out_len, 1, fp); fclose(fp); } static int util_proxy_dns(char *req_buff, int req_len, char *rsp_buff, int rsp_size) { int ret; int clientfd; struct sockaddr_in saddr; socklen_t addrlen = sizeof(struct sockaddr_in); clientfd = socket(AF_INET, SOCK_DGRAM, 0); if (clientfd == -1) { ERROR("socket() failed\n"); } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = PF_INET; saddr.sin_port = htons(53); saddr.sin_addr.s_addr = inet_addr("114.114.114.114"); ret = sendto(clientfd, req_buff, req_len, 0, (struct sockaddr *)&saddr, addrlen); if (ret < 0) { ERROR("sendto() failed\n"); } ret = recvfrom(clientfd, rsp_buff, rsp_size, 0, (struct sockaddr *)&saddr, &addrlen); if (ret < 0) { ERROR("recvfrom() failed\n"); } close(clientfd); return ret; } static int util_parser_dns(const char *buff, int len, char *out_buff, int size) { int ret; dns_info_t *parser = dns_new(); dns_info_t *package = dns_new(); assert(parser); assert(package); // buff to struct ret = dns_parser(parser, (char *)buff, len); if (ret == -1) { ERROR("dns_parser() failed\n"); } // struct to buff ret = dns_package(parser, out_buff, size); if (ret == -1) { ERROR("dns_package() failed\n"); } if (dns_parser(package, out_buff, ret) == -1) { ERROR("dns_parser() failed\n"); } printf("dns first parser\n"); dns_print(parser, "./dns_test_parser1.log"); printf("dns second parser\n"); dns_print(package, "./dns_test_parser2.log"); if (len != ret || strncmp(buff, out_buff, len) != 0) { printf("==================================\n" "first parser != second parser\n" "==================================\n"); } dns_free(parser); dns_free(package); return ret; } static void test_as_dns_proxy_not_cheat_respone(void) { int len; int ret; int listenfd = -1; int reuseaddr = 1; char req_buff[10240]; char rsp_buff[10240]; char req_pacakge[10240]; char rsp_package[10240]; struct sockaddr_in saddr; struct sockaddr_in caddr; socklen_t addrlen = sizeof(struct sockaddr_in); listenfd = socket(AF_INET, SOCK_DGRAM, 0); if (listenfd == -1) { ERROR("socket() failed\n"); } if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) == -1) { ERROR("setsockopt() failed\n"); } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = PF_INET; saddr.sin_port = htons(53); saddr.sin_addr.s_addr = INADDR_ANY; if (bind(listenfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr)) == -1) { ERROR("bind() failed\n"); } while (1) { memset(req_buff, 0, sizeof(req_buff)); memset(rsp_buff, 0, sizeof(rsp_buff)); ret = recvfrom(listenfd, req_buff, sizeof(req_buff), 0, (struct sockaddr *)&caddr, &addrlen); if (ret < 0) { ERROR("recvfrom() failed\n"); } // DNS 请求包 dump util_dump_dns(req_buff, ret, 1); // DNS 请求包 解析/封装 测试 printf("============ parser req ============\n"); len = util_parser_dns(req_buff, ret, req_pacakge, sizeof(req_pacakge)); ret = util_proxy_dns(req_buff, ret, rsp_buff, sizeof(rsp_buff)); // DNS 响应包 dump util_dump_dns(rsp_buff, ret, 0); // DNS 响应包 解析/封装 测试 printf("============ parser rsp ============\n"); len = util_parser_dns(rsp_buff, ret, rsp_package, sizeof(rsp_package)); ret = sendto(listenfd, rsp_package, len, 0, (struct sockaddr *)&caddr, addrlen); if (ret < 0) { ERROR("sendto() failed\n"); } } } static void test_as_dns_proxy_but_cheat_respone(void) { int ret; int listenfd = -1; int reuseaddr = 1; char req_buff[10240]; char rsp_buff[10240]; struct sockaddr_in saddr; struct sockaddr_in caddr; socklen_t addrlen = sizeof(struct sockaddr_in); listenfd = socket(AF_INET, SOCK_DGRAM, 0); if (listenfd == -1) { ERROR("socket() failed\n"); } if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) == -1) { ERROR("setsockopt() failed\n"); } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = PF_INET; saddr.sin_port = htons(53); saddr.sin_addr.s_addr = INADDR_ANY; if (bind(listenfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr)) == -1) { ERROR("bind() failed\n"); } cheat_pkt_opt_t cheat_opt[32]; memset(cheat_opt, 0, sizeof(cheat_opt)); // DNS_TYPE_A cheat_opt[0].res_type = DNS_TYPE_A; cheat_opt[0].ttl = 30; cheat_opt[0].res_len = 4; inet_pton(AF_INET, "192.168.1.1", cheat_opt[0].res_info); // DNS_TYPE_AAAA cheat_opt[1].res_type = DNS_TYPE_AAAA; cheat_opt[1].ttl = 60; cheat_opt[1].res_len = 16; inet_pton(AF_INET6, "fe80::230:64ff:fe57:4a15", cheat_opt[1].res_info); // DNS_TYPE_CNAME cheat_opt[2].res_type = DNS_TYPE_CNAME; cheat_opt[2].ttl = 90; cheat_opt[2].res_len = sizeof("www.cname1.com"); memcpy(cheat_opt[2].res_info, "www.cname1.com", cheat_opt[2].res_len); // DNS_TYPE_NS cheat_opt[3].res_type = DNS_TYPE_NS; cheat_opt[3].ttl = 90; cheat_opt[3].res_len = sizeof("www.ns.com"); memcpy(cheat_opt[3].res_info, "www.ns.com", cheat_opt[3].res_len); while (1) { memset(req_buff, 0, sizeof(req_buff)); memset(rsp_buff, 0, sizeof(rsp_buff)); ret = recvfrom(listenfd, req_buff, sizeof(req_buff), 0, (struct sockaddr *)&caddr, &addrlen); if (ret < 0) { ERROR("recvfrom() failed\n"); } // DNS 请求包 dump util_dump_dns(req_buff, ret, 1); // 解析 DNS 请求包 dns_info_t *parser = dns_new(); assert(parser); ret = dns_parser(parser, req_buff, ret); if (ret == -1) { ERROR("dns_parser() failed\n"); } // 扫描策略 // 若命中策略,根据策略信息伪造 DNS 响应 // 伪造 DNS 响应包 ret = dns_cheat_response(parser, cheat_opt, 4, rsp_buff, sizeof(rsp_buff)); if (ret == -1) { ERROR("dns_cheat_response() failed\n"); } dns_free(parser); // DNS 响应包 dump util_dump_dns(rsp_buff, ret, 0); ret = sendto(listenfd, rsp_buff, ret, 0, (struct sockaddr *)&caddr, addrlen); if (ret < 0) { ERROR("sendto() failed\n"); } } } static void test_use_offline_package(void) { int i; int req_len; int rsp_len; char req_buff[102400] = {0}; char rsp_buff[102400] = {0}; char out_buff[102400 * 2] = {0}; for (i = 0; i < package_arry_size; i++) { printf("test[%d]: %s\n", i, package_arry[i].desc); req_len = base64_decode(req_buff, sizeof(req_buff), package_arry[i].req.data, package_arry[i].req.len); if (req_len == MS_ERROR) { ERROR("base64_encode() failed\n"); } printf("============ parser req ============\n"); util_parser_dns(req_buff, req_len, out_buff, sizeof(out_buff)); rsp_len = base64_decode(rsp_buff, sizeof(rsp_buff), package_arry[i].rsp.data, package_arry[i].rsp.len); if (rsp_len == MS_ERROR) { ERROR("base64_encode() failed\n"); } printf("============ parser rsp ============\n"); util_parser_dns(rsp_buff, rsp_len, out_buff, sizeof(out_buff)); } } static void test_use_stdin_package(char *package) { int req_len; char req_buff[102400] = {0}; char out_buff[102400 * 2] = {0}; req_len = base64_decode(req_buff, sizeof(req_buff), package, strlen(package)); if (req_len == MS_ERROR) { ERROR("base64_encode() failed\n"); } util_parser_dns(req_buff, req_len, out_buff, sizeof(out_buff)); } static void usage(char *name) { printf("Usage: %s [option]\n" " -p : test as dns proxy not cheat respone (dig @127.0.0.1 www.baidu.com a) dump data in base64\n" " -c : test as dns proxy but cheat respone (dig @127.0.0.1 www.baidu.com a) dump data in base64\n" "\n" " -o : test use offline dns package\n" " -b ${base64_pack} : test use stdin dns package\n", name); exit(0); } int main(int argc, char **argv) { if (argc != 2 && argc != 3) { usage(argv[0]); } if (argc == 2 && (strncmp(argv[1], "-o", 2) != 0 && strncmp(argv[1], "-p", 2) != 0 && strncmp(argv[1], "-c", 2) != 0)) { usage(argv[0]); } if (argc == 3 && strncmp(argv[1], "-b", 2) != 0) { usage(argv[0]); } if (strncmp(argv[1], "-p", 2) == 0) { test_as_dns_proxy_not_cheat_respone(); } else if (strncmp(argv[1], "-c", 2) == 0) { test_as_dns_proxy_but_cheat_respone(); } else if (strncmp(argv[1], "-o", 2) == 0) { test_use_offline_package(); } else if (strncmp(argv[1], "-b", 2) == 0) { test_use_stdin_package(argv[2]); } return 0; }