diff --git a/dns.c b/dns.c index e1e6d6d..af1dcaf 100644 --- a/dns.c +++ b/dns.c @@ -1,102 +1,222 @@ #include "dns.h" +#include +#include #define DNS_MAX_CNAME_LEN 128 -int dns_decode_head(struct dns_head *head, struct idns_head *ihead) +short dns_read_short(unsigned char **buffer) { - 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); + unsigned short value; + value = *((unsigned short *)(*buffer)); + *buffer += 2; + + return ntohs(value); +} + +void dns_write_char(unsigned char **buffer, unsigned char value) +{ + **buffer = value; + *buffer += 1; +} + +unsigned char dns_read_char(unsigned char **buffer) +{ + unsigned char value = **buffer; + *buffer += 1; + return value; +} + +void dns_write_short(unsigned char **buffer, unsigned short value) +{ + value = htons(value); + *((unsigned short *)(*buffer)) = value; + *buffer += 2; +} + +void dns_write_int(unsigned char **buffer, unsigned int value) +{ + value = htons(value); + *((unsigned int *)(*buffer)) = value; + *buffer += 4; +} + +unsigned int dns_read_int(unsigned char **buffer) +{ + unsigned int value; + + value = *((unsigned int *)(*buffer)); + *buffer += 4; + + return ntohs(value); +} + +int dns_decode_head(struct dns_head *head, unsigned char **data) +{ + unsigned int fields; + unsigned char *start = *data; + unsigned char *end = start; + + head->id = dns_read_short(data); + fields = dns_read_short(data); + head->qr = (fields & QR_MASK) >> 15; + head->opcode = (fields & OPCODE_MASK) >> 11; + head->aa = (fields & AA_MASK) >> 10; + head->tc = (fields & TC_MASK) >> 9; + head->rd = (fields & RD_MASK) >> 8; + head->ra = (fields & RA_MASK) >> 7; + head->rcode = (fields & RCODE_MASK) >> 0; + head->qdcount = dns_read_short(data); + head->ancount = dns_read_short(data); + head->nscount = dns_read_short(data); + head->nrcount = dns_read_short(data); + + end = *data; + return start - end; +} + +int dns_encode_head(unsigned char **data, struct dns_head *head) +{ + dns_write_short(data, head->id); + + int fields = 0; + fields |= (head->qr << 15) & QR_MASK; + fields |= (head->rcode << 0) & RCODE_MASK; + dns_write_short(data, fields); + + dns_write_short(data, head->qdcount); + dns_write_short(data, head->ancount); + dns_write_short(data, head->nscount); + dns_write_short(data, head->nrcount); return 0; } -int dns_decode_rr(char *data, int size) +int dns_get_domain(char *output, int size, unsigned char *data) { - int ret; - int len = 0; + int i = 0; + int output_len = 0; + int copy_len = 0; + int total_len = 0; - return len; -} + while (data[i]) { + int len = data[i]; -int dns_get_domain(char *data, int size, char *output) -{ - int i = 0; + if (i != 0) { + *output = '.'; + output++; + } - while (data[i]) { - int len = data[i]; - *output = '.'; - output++; i++; - memcpy(output, data + i, len); + total_len++; + if (output_len < size - 1) { + copy_len = (len < size - output_len) ? len : size - 1 - output_len; + memcpy(output, data + i, copy_len); + } i += len; output += len; + output_len += len; + total_len += len; } - int qtype = (unsigned short) data[i+1]; - int qclass = (unsigned short) data[i+3]; - - return 0; + *output = 0; + total_len++; + return total_len; } -int dns_decode_qd(char *data, int size) +int dns_encode_domain(unsigned char *output, int size, char *domain) +{ + int i = 0; + int num = 0; + int total_len = 0; + unsigned char *ptr_num = output++; + total_len++; + while (i < size && *domain != 0) { + if (*domain == '.') { + *ptr_num = num; + num = 0; + ptr_num = output; + domain++; + output++; + total_len++; + continue; + } + *output = *domain; + num++; + output++; + domain++; + total_len++; + } + *ptr_num = num; + *output = 0; + total_len++; + return total_len; +} + +int dns_decode_qd(unsigned char *data, int size, char *domain, int domain_size, int *qtype, int *qclass) { - int ret; int len = 0; - char name[DNS_MAX_CNAME_LEN]; - len = dns_get_domain(data, size, name); - printf("%s\n", name); + len = dns_get_domain(domain, domain_size, data); + data += len; + *qtype = dns_read_short(&data); + *qclass = dns_read_short(&data); return len; } -int dns_decode_body(struct dns_packet *packet, char *data, int size) +int dns_decode_body(struct dns_packet *packet, unsigned char *data, int size) { struct dns_head *head = &packet->head; int i = 0; int len = 0; int decode_len = 0; + int qtype = 0; + int qclass = 0; + char name[DNS_MAX_CNAME_LEN]; + + if (head->nrcount || head->nscount || head->ancount) { + return -1; + } for (i = 0; i < head->qdcount; i++) { - len = dns_decode_qd(data, size - decode_len); - + len = dns_decode_qd(data, size - decode_len, name, DNS_MAX_CNAME_LEN, &qtype, &qclass); + printf("QR: %d, domain: %s, qtype = %d, qclass = %d\n", head->qr, name, qtype, qclass); 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) +int dns_decode(struct dns_packet *packet, unsigned char *data, int size) { - struct idns_head *ihead = (struct idns_head *)data; struct dns_head *head = &packet->head; int decode_len = 0; + int ret = 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; + decode_len = dns_decode_head(head, &data); + ret = dns_decode_body(packet, data, size - decode_len); + return ret; +} + + +int dns_encode(unsigned char *data, int size, struct dns_packet *packet) +{ + int rc; + int len = 0; + + len = dns_encode_head(&data, &packet->head); + + while (1) { + len = dns_encode_domain(data, size, "www.baidu.com"); + data += len; + dns_write_short(&data, /*qType*/12); + dns_write_short(&data, /*qClass*/ 1); + } + + /* + rc |= dns_encode_resource_records(packet->answers, data); + rc |= dns_encode_resource_records(packet->nameservers, data); + rc |= dns_encode_resource_records(packet->additional, data); + */ + return rc; } \ No newline at end of file diff --git a/dns.h b/dns.h index c1ddc6c..24625e5 100644 --- a/dns.h +++ b/dns.h @@ -1,23 +1,22 @@ #ifndef _DNS_HEAD_H #define _DNS_HEAD_H -#include #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; +#define QR_MASK 0x8000 +#define OPCODE_MASK 0x7800 +#define AA_MASK 0x0400 +#define TC_MASK 0x0200 +#define RD_MASK 0x0100 +#define RA_MASK 0x8000 +#define RCODE_MASK 0x000F -typedef enum dns_class { - DNS_C_IN = 1, - DNS_C_ANY = 255 -} dns_class_t; +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, @@ -58,36 +57,22 @@ typedef enum dns_rtcode { 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)); +} dns_rtcode_t; /* dns_rcode */ 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 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)); + unsigned short id; // identification number + unsigned short qr; /* Query/Response Flag */ + unsigned short opcode; /* Operation Code */ + unsigned short aa; /* Authoritative Answer Flag */ + unsigned short tc; /* Truncation Flag */ + unsigned short rd; /* Recursion Desired */ + unsigned short ra; /* Recursion Available */ + unsigned short rcode; /* Response Code */ + 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 addititional resource entries +} __attribute__((packed)); struct dns_qds { unsigned short type; @@ -104,75 +89,73 @@ struct dns_rrs { typedef uint32_t TTL; -typedef struct dns_question_t /* RFC-1035 */ +typedef struct dns_question_t /* RFC-1035 */ { - const char *name; - dns_type_t type; - dns_class_t class; + const char *name; + dns_type_t type; + dns_class_t class; } dns_question_t; -typedef struct dns_generic_t /* RFC-1035 */ +typedef struct dns_generic_t /* RFC-1035 */ { - const char *name; - dns_type_t type; - dns_class_t class; - TTL ttl; + const char *name; + dns_type_t type; + dns_class_t class; + TTL ttl; } dns_generic_t; -typedef struct dns_a_t /* RFC-1035 */ +typedef struct dns_a_t /* RFC-1035 */ { - const char *name; - dns_type_t type; - dns_class_t class; - TTL ttl; - in_addr_t address; + 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 */ +typedef struct dns_aaaa_t /* RFC-1886 */ { - const char *name; - dns_type_t type; - dns_class_t class; - TTL ttl; - struct in6_addr address; + 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 */ +typedef struct dns_cname_t /* RFC-1035 */ { - const char *name; - dns_type_t type; - dns_class_t class; - TTL ttl; - const char *cname; + 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 */ +typedef struct dns_ptr_t /* RFC-1035 */ { - const char *name; - dns_type_t type; - dns_class_t class; - TTL ttl; - const char *ptr; + 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; +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; + dns_answer_t *answers; + dns_answer_t *nameservers; + dns_answer_t *additional; }; -int dns_decode(struct dns_packet *packet, char *data, int size); +int dns_decode(struct dns_packet *packet, unsigned char *data, int size); #endif \ No newline at end of file diff --git a/dns_server.c b/dns_server.c index 93c3177..e248c29 100644 --- a/dns_server.c +++ b/dns_server.c @@ -51,8 +51,8 @@ void _dns_server_period_run() static int _dns_server_process(struct timeval *now) { int len; - char inpacket[DNS_INPACKET_SIZE]; - char rsppacket[DNS_INPACKET_SIZE]; + unsigned char inpacket[DNS_INPACKET_SIZE]; + unsigned char rsppacket[DNS_INPACKET_SIZE]; struct dns_packet *packet = (struct dns_packet *)rsppacket; struct sockaddr_storage from; socklen_t from_len = sizeof(from); diff --git a/smartdns b/smartdns new file mode 100644 index 0000000..afbfbeb Binary files /dev/null and b/smartdns differ diff --git a/test-dns.c b/test-dns.c index 2fbf486..4ae574a 100755 --- a/test-dns.c +++ b/test-dns.c @@ -701,7 +701,7 @@ int main() struct sockaddr_in addr; int nbytes, rc; int sock; - int port = 9000; + int port = 53; struct Message msg; memset(&msg, 0, sizeof(struct Message));