diff --git a/Makefile b/Makefile index cca0091..a8aec48 100755 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ BIN=smartdns -OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o -CFLAGS=-g -O0 -Wall +OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o dns.o +CFLAGS=-g -O0 -Wall CFLAGS +=-Iinclude -CXXFLAGS=-g -O0 -Wall -std=c++11 +CXXFLAGS=-g -O0 -Wall -std=c++11 CXXFLAGS +=-Iinclude .PHONY: all @@ -11,7 +11,7 @@ CXXFLAGS +=-Iinclude all: $(BIN) $(BIN) : $(OBJS) - $(CC) $(OBJS) -o $@ -lpthread + $(CC) $(OBJS) -o $@ -lpthread clean: $(RM) $(OBJS) $(BIN) \ No newline at end of file diff --git a/dns.c b/dns.c new file mode 100644 index 0000000..e1e6d6d --- /dev/null +++ b/dns.c @@ -0,0 +1,102 @@ +#include "dns.h" + +#define DNS_MAX_CNAME_LEN 128 + +int dns_decode_head(struct dns_head *head, struct idns_head *ihead) +{ + head->id = ntohs(ihead->id); + head->opcode = (ihead->opcode >> 3) & 0x0F; + head->query = (ihead->opcode & 0x80) != 0x80; + head->aa = (ihead->opcode & 0x04) == 0x04; + head->tc = (ihead->opcode & 0x02) == 0x02; + head->rd = (ihead->opcode & 0x01) == 0x01; + head->ra = (ihead->rcode & 0x80) == 0x80; + head->z = (ihead->rcode & 0x40) == 0x40; + head->ad = (ihead->rcode & 0x20) == 0x20; + head->cd = (ihead->rcode & 0x10) == 0x10; + head->rcode = (ihead->rcode & 0x0F); + head->qdcount = ntohs(ihead->qdcount); + head->ancount = ntohs(ihead->ancount); + head->nscount = ntohs(ihead->nscount); + head->nrcount = ntohs(ihead->arcount); + + return 0; +} + +int dns_decode_rr(char *data, int size) +{ + int ret; + int len = 0; + + return len; +} + +int dns_get_domain(char *data, int size, char *output) +{ + int i = 0; + + while (data[i]) { + int len = data[i]; + *output = '.'; + output++; + i++; + memcpy(output, data + i, len); + i += len; + output += len; + } + + int qtype = (unsigned short) data[i+1]; + int qclass = (unsigned short) data[i+3]; + + return 0; +} + +int dns_decode_qd(char *data, int size) +{ + int ret; + int len = 0; + char name[DNS_MAX_CNAME_LEN]; + len = dns_get_domain(data, size, name); + printf("%s\n", name); + + return len; +} + +int dns_decode_body(struct dns_packet *packet, char *data, int size) +{ + struct dns_head *head = &packet->head; + int i = 0; + int len = 0; + int decode_len = 0; + + for (i = 0; i < head->qdcount; i++) { + len = dns_decode_qd(data, size - decode_len); + + decode_len += len; + data += len; + } + + for (i = 0; i < head->qdcount; i++) { + } + + for (i = 0; i < head->qdcount; i++) { + } + + for (i = 0; i < head->qdcount; i++) { + } + + return 0; +} + +int dns_decode(struct dns_packet *packet, char *data, int size) +{ + struct idns_head *ihead = (struct idns_head *)data; + struct dns_head *head = &packet->head; + int decode_len = 0; + + dns_decode_head(head, ihead); + decode_len += sizeof(struct idns_head); + data += sizeof(struct idns_head); + dns_decode_body(packet, data, size - decode_len); + return -1; +} \ No newline at end of file diff --git a/dns.h b/dns.h index ce446ee..c1ddc6c 100644 --- a/dns.h +++ b/dns.h @@ -1,39 +1,178 @@ #ifndef _DNS_HEAD_H #define _DNS_HEAD_H -#pragma pack(push, 1) +#include +#include +#include +#include + +typedef enum dns_section { + DNS_S_QD = 0x01, + DNS_S_AN = 0x02, + DNS_S_NS = 0x04, + DNS_S_AR = 0x08, + DNS_S_ALL = 0x0f +} dns_section_t; + +typedef enum dns_class { + DNS_C_IN = 1, + DNS_C_ANY = 255 +} dns_class_t; + +typedef enum dns_type { + DNS_T_A = 1, + DNS_T_NS = 2, + DNS_T_CNAME = 5, + DNS_T_SOA = 6, + DNS_T_PTR = 12, + DNS_T_MX = 15, + DNS_T_TXT = 16, + DNS_T_AAAA = 28, + DNS_T_SRV = 33, + DNS_T_OPT = 41, + DNS_T_SSHFP = 44, + DNS_T_SPF = 99, + DNS_T_AXFR = 252, + DNS_T_ALL = 255 +} dns_type_t; + +typedef enum dns_opcode { + DNS_OP_QUERY = 0, + DNS_OP_IQUERY = 1, + DNS_OP_STATUS = 2, + DNS_OP_NOTIFY = 4, + DNS_OP_UPDATE = 5, +} dns_opcode_t; /* dns_opcode */ + +typedef enum dns_rtcode { + DNS_RC_NOERROR = 0, + DNS_RC_FORMERR = 1, + DNS_RC_SERVFAIL = 2, + DNS_RC_NXDOMAIN = 3, + DNS_RC_NOTIMP = 4, + DNS_RC_REFUSED = 5, + DNS_RC_YXDOMAIN = 6, + DNS_RC_YXRRSET = 7, + DNS_RC_NXRRSET = 8, + DNS_RC_NOTAUTH = 9, + DNS_RC_NOTZONE = 10, + /* EDNS(0) extended RCODEs */ + DNS_RC_BADVERS = 16, +} dns_rtcode_t ; /* dns_rcode */ + +struct idns_head +{ + unsigned short id; + unsigned char opcode; + unsigned char rcode; + unsigned short qdcount; + unsigned short ancount; + unsigned short nscount; + unsigned short arcount; +} __attribute__ ((packed)); struct dns_head { - unsigned short id; // identification number - unsigned char rd : 1; // recursion desired - unsigned char tc : 1; // truncated message - unsigned char aa : 1; // authoritive answer - unsigned char opcode : 4; // purpose of message - unsigned char qr : 1; // query/response flag - unsigned char rcode : 4; // response code - unsigned char cd : 1; // checking disabled - unsigned char ad : 1; // authenticated data - unsigned char z : 1; // its z! reserved - unsigned char ra : 1; // recursion available - unsigned short qd_count; // number of question entries - unsigned short an_count; // number of answer entries - unsigned short ns_count; // number of authority entries - unsigned short nr_count; // number of resource entries -}; + unsigned short id; // identification number + unsigned char rd : 1; // recursion desired + unsigned char tc : 1; // truncated message + unsigned char aa : 1; // authoritive answer + unsigned char opcode : 4; // purpose of message + unsigned char query : 1; // query/response flag + unsigned char rcode : 4; // response code + unsigned char cd : 1; // checking disabled + unsigned char ad : 1; // authenticated data + unsigned char z : 1; // its z! reserved + unsigned char ra : 1; // recursion available + unsigned short qdcount; // number of question entries + unsigned short ancount; // number of answer entries + unsigned short nscount; // number of authority entries + unsigned short nrcount; // number of resource entries +} __attribute__ ((packed)); struct dns_qds { - unsigned short type; - unsigned short classes; + unsigned short type; + unsigned short classes; }; struct dns_rrs { - unsigned short type; - unsigned short classes; - unsigned int ttl; - unsigned short rd_length; - char rd_data[0]; + unsigned short type; + unsigned short classes; + unsigned int ttl; + unsigned short rd_length; + char rd_data[0]; }; -#pragma pack(pop) +typedef uint32_t TTL; + +typedef struct dns_question_t /* RFC-1035 */ +{ + const char *name; + dns_type_t type; + dns_class_t class; +} dns_question_t; + +typedef struct dns_generic_t /* RFC-1035 */ +{ + const char *name; + dns_type_t type; + dns_class_t class; + TTL ttl; +} dns_generic_t; + +typedef struct dns_a_t /* RFC-1035 */ +{ + const char *name; + dns_type_t type; + dns_class_t class; + TTL ttl; + in_addr_t address; +} dns_a_t; + +typedef struct dns_aaaa_t /* RFC-1886 */ +{ + const char *name; + dns_type_t type; + dns_class_t class; + TTL ttl; + struct in6_addr address; +} dns_aaaa_t; + +typedef struct dns_cname_t /* RFC-1035 */ +{ + const char *name; + dns_type_t type; + dns_class_t class; + TTL ttl; + const char *cname; +} dns_cname_t; + +typedef struct dns_ptr_t /* RFC-1035 */ +{ + const char *name; + dns_type_t type; + dns_class_t class; + TTL ttl; + const char *ptr; +} dns_ptr_t; + + +typedef union dns_answer_t +{ + dns_generic_t generic; + dns_a_t a; + dns_cname_t cname; + dns_ptr_t ptr; + dns_aaaa_t aaaa; +} dns_answer_t; + +struct dns_packet { + struct dns_head head; + dns_question_t *questions; + dns_answer_t *answers; + dns_answer_t *nameservers; + dns_answer_t *additional; +}; + +int dns_decode(struct dns_packet *packet, char *data, int size); #endif \ No newline at end of file