From a1835eace3e91c58e6ec1d99da97fec2e8d26af3 Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Mon, 14 May 2018 23:16:21 +0800 Subject: [PATCH] update code --- dns.c | 1547 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 749 insertions(+), 798 deletions(-) diff --git a/dns.c b/dns.c index 576f478..f636817 100644 --- a/dns.c +++ b/dns.c @@ -6,442 +6,442 @@ short dns_read_short(unsigned char **buffer) { - unsigned short value; + unsigned short value; - value = *((unsigned short *)(*buffer)); - *buffer += 2; + value = *((unsigned short *)(*buffer)); + *buffer += 2; - return ntohs(value); + return ntohs(value); } void dns_write_char(unsigned char **buffer, unsigned char value) { - **buffer = value; - *buffer += 1; + **buffer = value; + *buffer += 1; } unsigned char dns_read_char(unsigned char **buffer) { - unsigned char value = **buffer; - *buffer += 1; - return value; + 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; + 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; + value = htons(value); + *((unsigned int *)(*buffer)) = value; + *buffer += 4; } unsigned int dns_read_int(unsigned char **buffer) { - unsigned int value; + unsigned int value; - value = *((unsigned int *)(*buffer)); - *buffer += 4; + value = *((unsigned int *)(*buffer)); + *buffer += 4; - return ntohs(value); + return ntohs(value); } struct dns_rrs *dns_get_rrs_start(struct dns_packet *packet, int type, int *count) { - unsigned short start; - struct dns_head *head = &packet->head; + unsigned short start; + struct dns_head *head = &packet->head; - switch (type) { - case DNS_RRS_QD: - *count = head->qdcount; - start = packet->questions; - break; - case DNS_RRS_AN: - *count = head->ancount; - start = packet->answers; - break; - case DNS_RRS_NS: - *count = head->nscount; - start = packet->nameservers; - break; - case DNS_RRS_NR: - *count = head->nrcount; - start = packet->additional; - break; - default: - return NULL; - break; - } + switch (type) { + case DNS_RRS_QD: + *count = head->qdcount; + start = packet->questions; + break; + case DNS_RRS_AN: + *count = head->ancount; + start = packet->answers; + break; + case DNS_RRS_NS: + *count = head->nscount; + start = packet->nameservers; + break; + case DNS_RRS_NR: + *count = head->nrcount; + start = packet->additional; + break; + default: + return NULL; + break; + } - if (start == DNS_RR_END) { - return NULL; - } + if (start == DNS_RR_END) { + return NULL; + } - return (struct dns_rrs *)(packet->data + start); + return (struct dns_rrs *)(packet->data + start); } struct dns_rrs *dns_get_rrs_next(struct dns_packet *packet, struct dns_rrs *rrs) { - if (rrs->next == DNS_RR_END) { - return NULL; - } + if (rrs->next == DNS_RR_END) { + return NULL; + } - return (struct dns_rrs *)(packet->data + rrs->next); + return (struct dns_rrs *)(packet->data + rrs->next); } unsigned char *_dns_add_rrs_start(struct dns_packet *packet, int *maxlen) { - struct dns_rrs *rrs; - unsigned char *end = packet->data + packet->len; - rrs = (struct dns_rrs *)end; - *maxlen = packet->size - packet->len - sizeof(*packet); - if (packet->len >= packet->size - sizeof(*packet)) { - return NULL; - } - return rrs->data; + struct dns_rrs *rrs; + unsigned char *end = packet->data + packet->len; + rrs = (struct dns_rrs *)end; + *maxlen = packet->size - packet->len - sizeof(*packet); + if (packet->len >= packet->size - sizeof(*packet)) { + return NULL; + } + return rrs->data; } int dns_rr_add_end(struct dns_packet *packet, int type, dns_type_t rrtype, int len) { - struct dns_rrs *rrs; - struct dns_head *head = &packet->head; - unsigned char *end = packet->data + packet->len; - rrs = (struct dns_rrs *)end; - unsigned short *count; - unsigned short *start; + struct dns_rrs *rrs; + struct dns_head *head = &packet->head; + unsigned char *end = packet->data + packet->len; + rrs = (struct dns_rrs *)end; + unsigned short *count; + unsigned short *start; - if (packet->len + len > packet->size - sizeof(*packet)) { - return -1; - } + if (packet->len + len > packet->size - sizeof(*packet)) { + return -1; + } - switch (type) { - case DNS_RRS_QD: - count = &head->qdcount; - start = &packet->questions; - break; - case DNS_RRS_AN: - count = &head->ancount; - start = &packet->answers; - break; - case DNS_RRS_NS: - count = &head->nscount; - start = &packet->nameservers; - break; - case DNS_RRS_NR: - count = &head->nrcount; - start = &packet->additional; - break; - default: - return -1; - break; - } + switch (type) { + case DNS_RRS_QD: + count = &head->qdcount; + start = &packet->questions; + break; + case DNS_RRS_AN: + count = &head->ancount; + start = &packet->answers; + break; + case DNS_RRS_NS: + count = &head->nscount; + start = &packet->nameservers; + break; + case DNS_RRS_NR: + count = &head->nrcount; + start = &packet->additional; + break; + default: + return -1; + break; + } - *count += 1; - rrs->next = *start; - rrs->len = len; - rrs->type = rrtype; - *start = packet->len; - packet->len += len + sizeof(*rrs); - return 0; + *count += 1; + rrs->next = *start; + rrs->len = len; + rrs->type = rrtype; + *start = packet->len; + packet->len += len + sizeof(*rrs); + return 0; } static inline int _dns_data_left_len(struct dns_data_context *data_context) { - return data_context->maxsize - (data_context->ptr - data_context->data); + return data_context->maxsize - (data_context->ptr - data_context->data); } int _dns_add_qr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass) { - while (1) { - if (_dns_data_left_len(data_context) < 1) { - return -1; - } - *data_context->ptr = *domain; - if (*domain == '\0') { - data_context->ptr++; - break; - } - data_context->ptr++; - domain++; - } + while (1) { + if (_dns_data_left_len(data_context) < 1) { + return -1; + } + *data_context->ptr = *domain; + if (*domain == '\0') { + data_context->ptr++; + break; + } + data_context->ptr++; + domain++; + } - if (_dns_data_left_len(data_context) < 4) { - return -1; - } + if (_dns_data_left_len(data_context) < 4) { + return -1; + } - *((unsigned short *)(data_context->ptr)) = qtype; - data_context->ptr += 2; + *((unsigned short *)(data_context->ptr)) = qtype; + data_context->ptr += 2; - *((unsigned short *)(data_context->ptr)) = qclass; - data_context->ptr += 2; + *((unsigned short *)(data_context->ptr)) = qclass; + data_context->ptr += 2; - return 0; + return 0; } int _dns_get_qr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass) { - int i; + int i; - for (i = 0; i < maxsize; i++) { - if (_dns_data_left_len(data_context) < 1) { - return -1; - } - *domain = *data_context->ptr; - if (*data_context->ptr == '\0') { - domain++; - data_context->ptr++; - i++; - break; - } - *domain = *data_context->ptr; - domain++; - data_context->ptr++; - } + for (i = 0; i < maxsize; i++) { + if (_dns_data_left_len(data_context) < 1) { + return -1; + } + *domain = *data_context->ptr; + if (*data_context->ptr == '\0') { + domain++; + data_context->ptr++; + i++; + break; + } + *domain = *data_context->ptr; + domain++; + data_context->ptr++; + } - if (_dns_data_left_len(data_context) < 4) { - return -1; - } + if (_dns_data_left_len(data_context) < 4) { + return -1; + } - *qtype = *((unsigned short *)(data_context->ptr)); - data_context->ptr += 2; + *qtype = *((unsigned short *)(data_context->ptr)); + data_context->ptr += 2; - *qclass = *((unsigned short *)(data_context->ptr)); - data_context->ptr += 2; + *qclass = *((unsigned short *)(data_context->ptr)); + data_context->ptr += 2; - return 0; + return 0; } int _dns_add_rr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass, int ttl, int rr_len) { - int len = 0; + int len = 0; - len = _dns_add_qr_head(data_context, domain, qtype, qclass); - if (len < 0) { - return -1; - } + len = _dns_add_qr_head(data_context, domain, qtype, qclass); + if (len < 0) { + return -1; + } - if (_dns_data_left_len(data_context) < 6) { - return -1; - } + if (_dns_data_left_len(data_context) < 6) { + return -1; + } - *((unsigned int *)(data_context->ptr)) = ttl; - data_context->ptr += 4; + *((unsigned int *)(data_context->ptr)) = ttl; + data_context->ptr += 4; - *((unsigned short *)(data_context->ptr)) = rr_len; - data_context->ptr += 2; + *((unsigned short *)(data_context->ptr)) = rr_len; + data_context->ptr += 2; - return 0; + return 0; } int _dns_get_rr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass, int *ttl, int *rr_len) { - int len = 0; + int len = 0; - len = _dns_get_qr_head(data_context, domain, maxsize, qtype, qclass); + len = _dns_get_qr_head(data_context, domain, maxsize, qtype, qclass); - if (_dns_data_left_len(data_context) < 6) { - return -1; - } + if (_dns_data_left_len(data_context) < 6) { + return -1; + } - *ttl = *((unsigned int *)(data_context->ptr)); - data_context->ptr += 4; + *ttl = *((unsigned int *)(data_context->ptr)); + data_context->ptr += 4; - *rr_len = *((unsigned short *)(data_context->ptr)); - data_context->ptr += 2; + *rr_len = *((unsigned short *)(data_context->ptr)); + data_context->ptr += 2; - return len; + return len; } int dns_add_CNAME(struct dns_packet *packet, char *domain, int ttl, char *cname) { - int maxlen = 0; - int len = 0; - struct dns_data_context data_context; - int rr_len = 0; + int maxlen = 0; + int len = 0; + struct dns_data_context data_context; + int rr_len = 0; - rr_len = strnlen(cname, maxlen - 1) + 1; - unsigned char *data = _dns_add_rrs_start(packet, &maxlen); - if (data == NULL) { - return -1; - } + rr_len = strnlen(cname, maxlen - 1) + 1; + unsigned char *data = _dns_add_rrs_start(packet, &maxlen); + if (data == NULL) { + return -1; + } - if (rr_len >= maxlen) { - return -1; - } + if (rr_len >= maxlen) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = maxlen; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = maxlen; - len = _dns_add_rr_head(&data_context, domain, DNS_T_CNAME, DNS_C_IN, ttl, rr_len); - if (len < 0) { - return -1; - } + len = _dns_add_rr_head(&data_context, domain, DNS_T_CNAME, DNS_C_IN, ttl, rr_len); + if (len < 0) { + return -1; + } - memcpy(data_context.ptr, cname, rr_len); - data_context.ptr += rr_len; - len = data_context.ptr - data_context.data; + memcpy(data_context.ptr, cname, rr_len); + data_context.ptr += rr_len; + len = data_context.ptr - data_context.data; - return dns_rr_add_end(packet, DNS_RRS_AN, DNS_T_CNAME, len); + return dns_rr_add_end(packet, DNS_RRS_AN, DNS_T_CNAME, len); } int dns_get_CNAME(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size) { - int qtype = 0; - int qclass = 0; - int rr_len = 0; - int ret = 0; - struct dns_data_context data_context; + int qtype = 0; + int qclass = 0; + int rr_len = 0; + int ret = 0; + struct dns_data_context data_context; - unsigned char *data = rrs->data; + unsigned char *data = rrs->data; - if (rrs->type != DNS_T_CNAME) { - return -1; - } + if (rrs->type != DNS_T_CNAME) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = rrs->len; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = rrs->len; - ret = _dns_get_rr_head(&data_context, domain, maxsize, &qtype, &qclass, ttl, &rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_get_rr_head(&data_context, domain, maxsize, &qtype, &qclass, ttl, &rr_len); + if (ret < 0) { + return -1; + } - if (qtype != DNS_T_CNAME || rr_len > cname_size) { - return -1; - } + if (qtype != DNS_T_CNAME || rr_len > cname_size) { + return -1; + } - memcpy(cname, data_context.ptr, rr_len); + memcpy(cname, data_context.ptr, rr_len); - return 0; + return 0; } int dns_add_A(struct dns_packet *packet, char *domain, int ttl, unsigned char addr[4]) { - int maxlen = 0; - int len = 0; - struct dns_data_context data_context; + int maxlen = 0; + int len = 0; + struct dns_data_context data_context; - unsigned char *data = _dns_add_rrs_start(packet, &maxlen); - if (data == NULL) { - return -1; - } + unsigned char *data = _dns_add_rrs_start(packet, &maxlen); + if (data == NULL) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = maxlen; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = maxlen; - len = _dns_add_rr_head(&data_context, domain, DNS_T_A, DNS_C_IN, ttl, DNS_RR_A_LEN); - if (len < 0) { - return -1; - } + len = _dns_add_rr_head(&data_context, domain, DNS_T_A, DNS_C_IN, ttl, DNS_RR_A_LEN); + if (len < 0) { + return -1; + } - memcpy(data_context.ptr, addr, DNS_RR_A_LEN); - data_context.ptr += DNS_RR_A_LEN; - len = data_context.ptr - data_context.data; + memcpy(data_context.ptr, addr, DNS_RR_A_LEN); + data_context.ptr += DNS_RR_A_LEN; + len = data_context.ptr - data_context.data; - return dns_rr_add_end(packet, DNS_RRS_AN, DNS_T_A, len); + return dns_rr_add_end(packet, DNS_RRS_AN, DNS_T_A, len); } int dns_get_A(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[4]) { - int qtype = 0; - int qclass = 0; - int rr_len = 0; - int ret = 0; - struct dns_data_context data_context; + int qtype = 0; + int qclass = 0; + int rr_len = 0; + int ret = 0; + struct dns_data_context data_context; - unsigned char *data = rrs->data; + unsigned char *data = rrs->data; - if (rrs->type != DNS_T_A) { - return -1; - } + if (rrs->type != DNS_T_A) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = rrs->len; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = rrs->len; - ret = _dns_get_rr_head(&data_context, domain, maxsize, &qtype, &qclass, ttl, &rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_get_rr_head(&data_context, domain, maxsize, &qtype, &qclass, ttl, &rr_len); + if (ret < 0) { + return -1; + } - if (qtype != DNS_T_A || rr_len != DNS_RR_A_LEN) { - return -1; - } + if (qtype != DNS_T_A || rr_len != DNS_RR_A_LEN) { + return -1; + } - memcpy(addr, data_context.ptr, DNS_RR_A_LEN); + memcpy(addr, data_context.ptr, DNS_RR_A_LEN); - return 0; + return 0; } int dns_add_AAAA(struct dns_packet *packet, char *domain, int ttl, unsigned char addr[16]) { - int maxlen = 0; - int len = 0; - struct dns_data_context data_context; + int maxlen = 0; + int len = 0; + struct dns_data_context data_context; - unsigned char *data = _dns_add_rrs_start(packet, &maxlen); - if (data == NULL) { - return -1; - } + unsigned char *data = _dns_add_rrs_start(packet, &maxlen); + if (data == NULL) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = maxlen; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = maxlen; - len = _dns_add_rr_head(&data_context, domain, DNS_T_AAAA, DNS_C_IN, ttl, DNS_RR_AAAA_LEN); - if (len < 0) { - return -1; - } + len = _dns_add_rr_head(&data_context, domain, DNS_T_AAAA, DNS_C_IN, ttl, DNS_RR_AAAA_LEN); + if (len < 0) { + return -1; + } - memcpy(data_context.ptr, addr, DNS_RR_AAAA_LEN); - data_context.ptr += DNS_RR_AAAA_LEN; - len = data_context.ptr - data_context.data; + memcpy(data_context.ptr, addr, DNS_RR_AAAA_LEN); + data_context.ptr += DNS_RR_AAAA_LEN; + len = data_context.ptr - data_context.data; - return dns_rr_add_end(packet, DNS_RRS_AN, DNS_T_AAAA, len); + return dns_rr_add_end(packet, DNS_RRS_AN, DNS_T_AAAA, len); } int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[16]) { - int qtype = 0; - int qclass = 0; - int rr_len = 0; - int ret = 0; - struct dns_data_context data_context; + int qtype = 0; + int qclass = 0; + int rr_len = 0; + int ret = 0; + struct dns_data_context data_context; - if (rrs->type != DNS_T_AAAA) { - return -1; - } + if (rrs->type != DNS_T_AAAA) { + return -1; + } - unsigned char *data = rrs->data; + unsigned char *data = rrs->data; - if (rrs->type != DNS_T_AAAA) { - return -1; - } + if (rrs->type != DNS_T_AAAA) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = rrs->len; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = rrs->len; - ret = _dns_get_rr_head(&data_context, domain, maxsize, &qtype, &qclass, ttl, &rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_get_rr_head(&data_context, domain, maxsize, &qtype, &qclass, ttl, &rr_len); + if (ret < 0) { + return -1; + } - if (qtype != DNS_T_AAAA || rr_len != DNS_RR_AAAA_LEN) { - return -1; - } + if (qtype != DNS_T_AAAA || rr_len != DNS_RR_AAAA_LEN) { + return -1; + } - memcpy(addr, data_context.ptr, DNS_RR_AAAA_LEN); + memcpy(addr, data_context.ptr, DNS_RR_AAAA_LEN); - return 0; + return 0; } /* @@ -450,705 +450,656 @@ int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsig */ int dns_add_domain(struct dns_packet *packet, char *domain, int qtype, int qclass) { - int len = 0; - int maxlen = 0; - unsigned char *data = _dns_add_rrs_start(packet, &maxlen); - struct dns_data_context data_context; + int len = 0; + int maxlen = 0; + unsigned char *data = _dns_add_rrs_start(packet, &maxlen); + struct dns_data_context data_context; - if (data == NULL) { - return -1; - } + if (data == NULL) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = maxlen; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = maxlen; - len = _dns_add_qr_head(&data_context, domain, qtype, qclass); - if (len < 0) { - return -1; - } + len = _dns_add_qr_head(&data_context, domain, qtype, qclass); + if (len < 0) { + return -1; + } - len = data_context.ptr - data_context.data; + len = data_context.ptr - data_context.data; - return dns_rr_add_end(packet, DNS_RRS_QD, DNS_T_CNAME, len); + return dns_rr_add_end(packet, DNS_RRS_QD, DNS_T_CNAME, len); } int dns_get_domain(struct dns_rrs *rrs, char *domain, int maxsize, int *qtype, int *qclass) { - struct dns_data_context data_context; - unsigned char *data = rrs->data; + struct dns_data_context data_context; + unsigned char *data = rrs->data; - if (rrs->type != DNS_T_CNAME) { - return -1; - } + if (rrs->type != DNS_T_CNAME) { + return -1; + } - data_context.data = data; - data_context.ptr = data; - data_context.maxsize = rrs->len; + data_context.data = data; + data_context.ptr = data; + data_context.maxsize = rrs->len; - return _dns_get_qr_head(&data_context, domain, maxsize, qtype, qclass); + return _dns_get_qr_head(&data_context, domain, maxsize, qtype, qclass); } static inline int _dns_left_len(struct dns_context *context) { - return context->maxsize - (context->ptr - context->data); + return context->maxsize - (context->ptr - context->data); } int _dns_decode_head(struct dns_context *context) { - unsigned int fields; - int len = 12; - struct dns_head *head = &context->packet->head; + unsigned int fields; + int len = 12; + struct dns_head *head = &context->packet->head; - if (_dns_left_len(context) < len) { - return -1; - } + if (_dns_left_len(context) < len) { + return -1; + } - head->id = dns_read_short(&context->ptr); - fields = dns_read_short(&context->ptr); - 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(&context->ptr); - head->ancount = dns_read_short(&context->ptr); - head->nscount = dns_read_short(&context->ptr); - head->nrcount = dns_read_short(&context->ptr); + head->id = dns_read_short(&context->ptr); + fields = dns_read_short(&context->ptr); + 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(&context->ptr); + head->ancount = dns_read_short(&context->ptr); + head->nscount = dns_read_short(&context->ptr); + head->nrcount = dns_read_short(&context->ptr); - return 0; + printf("qd = %d, an = %d\n", head->qdcount, head->ancount); + return 0; } int _dns_encode_head(struct dns_context *context) { - int len = 12; - struct dns_head *head = &context->packet->head; + int len = 12; + struct dns_head *head = &context->packet->head; - if (_dns_left_len(context) < len) { - return -1; - } + if (_dns_left_len(context) < len) { + return -1; + } - dns_write_short(&context->ptr, head->id); + dns_write_short(&context->ptr, head->id); - int fields = 0; - fields |= (head->qr << 15) & QR_MASK; - fields |= (head->rcode << 0) & RCODE_MASK; - dns_write_short(&context->ptr, fields); + int fields = 0; + fields |= (head->qr << 15) & QR_MASK; + fields |= (head->rcode << 0) & RCODE_MASK; + dns_write_short(&context->ptr, fields); - dns_write_short(&context->ptr, head->qdcount); - dns_write_short(&context->ptr, head->ancount); - dns_write_short(&context->ptr, head->nscount); - dns_write_short(&context->ptr, head->nrcount); - return len; -} - -int dns_parse_domain(char *dns, int offset, char *domain, int *space) -{ - unsigned char val, *pval; - unsigned short len; - - int sp = 0; - int domain_len = 0; - int org = 1; - - while (1) { - pval = (unsigned char *)(dns + offset); - val = *pval; - - if (val == 0) { - domain[domain_len - 1] = 0; - domain_len--; - if (org) - sp++; - break; - } else if (val <= 63) { - memcpy(domain + domain_len, dns + offset + 1, val); - domain_len += val; - domain[domain_len] = '.'; - domain_len++; - - offset += (val + 1); - - if (org) - sp += (val + 1); - } else { - len = *(unsigned short *)(dns + offset); - len = ntohs(len); - len = len & (~0xc000); - - if (org) - sp += 2; - - org = 0; - offset = len; - } - } - - *space = sp; - - return 0; + dns_write_short(&context->ptr, head->qdcount); + dns_write_short(&context->ptr, head->ancount); + dns_write_short(&context->ptr, head->nscount); + dns_write_short(&context->ptr, head->nrcount); + return len; } int _dns_decode_domain(struct dns_context *context, char *output, int size) { - int output_len = 0; - int copy_len = 0; - int len = *(context->ptr); - unsigned char *ptr = context->ptr; - int is_compressed = 0; + int output_len = 0; + int copy_len = 0; + int len = *(context->ptr); + unsigned char *ptr = context->ptr; + int is_compressed = 0; - - int sp = 0; - dns_parse_domain(context->data, context->ptr - context->data, output, &sp); - context->ptr += sp; - return 0; - + while (1) { + len = *ptr; + if (len == 0) { + *output = 0; + ptr++; + break; + } - while (1) { - len = *ptr; - if (len == 0) { - *output = 0; - ptr++; - break; - } + if (len >= 0xC0) { + len = dns_read_short(&ptr) & 0x3FFF; + if (is_compressed == 0) { + context->ptr = ptr; + } + ptr = context->data + len; + if (context->maxsize - (ptr - context->data) < 1) { + return -1; + } + is_compressed = 1; + continue; + } - if (len >= 0xC0) { - ptr = context->data + (dns_read_short(&ptr) & 0x3FFF); - is_compressed = 1; - context->ptr += 2; - continue; - } + if (context->maxsize - (ptr - context->data) < 1) { + return -1; + } - if (context->maxsize - (ptr - context->data) < 1) { - return -1; - } + ptr++; + if (output_len < size - 1) { + copy_len = (len < size - output_len) ? len : size - 1 - output_len; + if (context->maxsize - (ptr - context->data) < 1) { + return -1; + } + memcpy(output, ptr, copy_len); + } - ptr++; - if (output_len < size - 1) { - copy_len = (len < size - output_len) ? len : size - 1 - output_len; - if (context->maxsize - (ptr - context->data) < 1) { - return -1; - } - memcpy(output, ptr, copy_len); - } + ptr += len; + output += len; + output_len += len; + *output = '.'; + output++; + } - ptr += len; - output += len; - output_len += len; - *output = '.'; - output++; - } + if (is_compressed == 0) { + context->ptr = ptr; + } - if (is_compressed == 0) { - context->ptr = ptr; - } - - printf("--%p\n", context->ptr); - - return 0; + return 0; } int _dns_encode_domain(struct dns_context *context, char *domain) { - int num = 0; - unsigned char *ptr_num = context->ptr++; + int num = 0; + unsigned char *ptr_num = context->ptr++; - while (_dns_left_len(context) > 1 && *domain != 0) { - if (*domain == '.') { - *ptr_num = num; - num = 0; - ptr_num = context->ptr; - domain++; - context->ptr++; - continue; - } - *context->ptr = *domain; - num++; - context->ptr++; - domain++; - } + while (_dns_left_len(context) > 1 && *domain != 0) { + if (*domain == '.') { + *ptr_num = num; + num = 0; + ptr_num = context->ptr; + domain++; + context->ptr++; + continue; + } + *context->ptr = *domain; + num++; + context->ptr++; + domain++; + } - *ptr_num = num; - *(context->ptr) = 0; - context->ptr++; - return 0; + *ptr_num = num; + *(context->ptr) = 0; + context->ptr++; + return 0; } int _dns_decode_qr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass) { - int ret = 0; + int ret = 0; - ret = _dns_decode_domain(context, domain, domain_size); - if (ret < 0) { - return -1; - } + ret = _dns_decode_domain(context, domain, domain_size); + if (ret < 0) { + return -1; + } - if (_dns_left_len(context) < 4) { - return -1; - } + if (_dns_left_len(context) < 4) { + return -1; + } - *qtype = dns_read_short(&context->ptr); - *qclass = dns_read_short(&context->ptr); + *qtype = dns_read_short(&context->ptr); + *qclass = dns_read_short(&context->ptr); - return 0; + return 0; } int _dns_encode_qr_head(struct dns_context *context, char *domain, int qtype, int qclass) { - int ret = 0; - ret = _dns_encode_domain(context, domain); - if (ret < 0) { - return -1; - } + int ret = 0; + ret = _dns_encode_domain(context, domain); + if (ret < 0) { + return -1; + } - if (_dns_left_len(context) < 4) { - return -1; - } + if (_dns_left_len(context) < 4) { + return -1; + } - dns_write_short(&context->ptr, qtype); - dns_write_short(&context->ptr, qclass); + dns_write_short(&context->ptr, qtype); + dns_write_short(&context->ptr, qclass); - return 0; + return 0; } int _dns_decode_rr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass, int *ttl, int *rr_len) { - int len = 0; + int len = 0; - len = _dns_decode_qr_head(context, domain, domain_size, qtype, qclass); - if (len < 0) { - return -1; - } + len = _dns_decode_qr_head(context, domain, domain_size, qtype, qclass); + if (len < 0) { + return -1; + } - if (_dns_left_len(context) < 6) { - return -1; - } + if (_dns_left_len(context) < 6) { + return -1; + } - *ttl = dns_read_int(&context->ptr); - *rr_len = dns_read_short(&context->ptr); + *ttl = dns_read_int(&context->ptr); + *rr_len = dns_read_short(&context->ptr); - return 0; + return 0; } int _dns_encode_rr_head(struct dns_context *context, char *domain, int qtype, int qclass, int ttl, int rr_len) { - int ret = 0; - ret = _dns_encode_qr_head(context, domain, qtype, qclass); - if (ret < 0) { - return -1; - } + int ret = 0; + ret = _dns_encode_qr_head(context, domain, qtype, qclass); + if (ret < 0) { + return -1; + } - if (_dns_left_len(context) < 6) { - return -1; - } + if (_dns_left_len(context) < 6) { + return -1; + } - dns_write_int(&context->ptr, ttl); - dns_write_short(&context->ptr, rr_len); + dns_write_int(&context->ptr, ttl); + dns_write_short(&context->ptr, rr_len); - return 0; + return 0; } int _dns_decode_CNAME(struct dns_context *context, char *cname, int cname_size) { - int ret = 0; - ret = _dns_decode_domain(context, cname, cname_size); - if (ret < 0) { - return -1; - } + int ret = 0; + ret = _dns_decode_domain(context, cname, cname_size); + if (ret < 0) { + return -1; + } - return 0; + return 0; } int _dns_encode_CNAME(struct dns_context *context, struct dns_rrs *rrs) { - int ret; - int qtype = 0; - int qclass = 0; - int ttl = 0; - char domain[DNS_MAX_CNAME_LEN]; - int rr_len; - struct dns_data_context data_context; + int ret; + int qtype = 0; + int qclass = 0; + int ttl = 0; + char domain[DNS_MAX_CNAME_LEN]; + int rr_len; + struct dns_data_context data_context; - data_context.data = rrs->data; - data_context.ptr = rrs->data; - data_context.maxsize = rrs->len; + data_context.data = rrs->data; + data_context.ptr = rrs->data; + data_context.maxsize = rrs->len; - ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); + if (ret < 0) { + return -1; + } - if (rr_len > rrs->len) { - return -1; - } + if (rr_len > rrs->len) { + return -1; + } - ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, rr_len); + if (ret < 0) { + return -1; + } - ret = _dns_encode_domain(context, (char *)rrs->data); - if (ret < 0) { - return -1; - } + ret = _dns_encode_domain(context, (char *)rrs->data); + if (ret < 0) { + return -1; + } - return 0; + return 0; } int _dns_decode_A(struct dns_context *context, unsigned char addr[4]) { - if (_dns_left_len(context) < DNS_RR_A_LEN) { - return -1; - } + if (_dns_left_len(context) < DNS_RR_A_LEN) { + return -1; + } - memcpy(addr, context->ptr, DNS_RR_A_LEN); - context->ptr += DNS_RR_A_LEN; - return 0; + memcpy(addr, context->ptr, DNS_RR_A_LEN); + context->ptr += DNS_RR_A_LEN; + return 0; } int _dns_encode_A(struct dns_context *context, struct dns_rrs *rrs) { - int ret; - int qtype = 0; - int qclass = 0; - int ttl = 0; - char domain[DNS_MAX_CNAME_LEN]; - int rr_len; - struct dns_data_context data_context; + int ret; + int qtype = 0; + int qclass = 0; + int ttl = 0; + char domain[DNS_MAX_CNAME_LEN]; + int rr_len; + struct dns_data_context data_context; - data_context.data = rrs->data; - data_context.ptr = rrs->data; - data_context.maxsize = rrs->len; + data_context.data = rrs->data; + data_context.ptr = rrs->data; + data_context.maxsize = rrs->len; - ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); + if (ret < 0) { + return -1; + } - if (rr_len != DNS_RR_A_LEN) { - return -1; - } + if (rr_len != DNS_RR_A_LEN) { + return -1; + } - ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, DNS_RR_A_LEN); - if (ret < 0) { - return -1; - } + ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, DNS_RR_A_LEN); + if (ret < 0) { + return -1; + } - if (_dns_left_len(context) < DNS_RR_A_LEN) { - return -1; - } + if (_dns_left_len(context) < DNS_RR_A_LEN) { + return -1; + } - memcpy(context->ptr, rrs->data, DNS_RR_A_LEN); - context->ptr += DNS_RR_A_LEN; + memcpy(context->ptr, rrs->data, DNS_RR_A_LEN); + context->ptr += DNS_RR_A_LEN; - return 0; + return 0; } int _dns_decode_AAAA(struct dns_context *context, unsigned char addr[DNS_RR_AAAA_LEN]) { - if (_dns_left_len(context) < DNS_RR_AAAA_LEN) { - return -1; - } + if (_dns_left_len(context) < DNS_RR_AAAA_LEN) { + return -1; + } - memcpy(addr, context->ptr, DNS_RR_AAAA_LEN); - context->ptr += DNS_RR_AAAA_LEN; - return 0; + memcpy(addr, context->ptr, DNS_RR_AAAA_LEN); + context->ptr += DNS_RR_AAAA_LEN; + return 0; } int _dns_encode_AAAA(struct dns_context *context, struct dns_rrs *rrs) { - int ret; - int qtype = 0; - int qclass = 0; - int ttl = 0; - char domain[DNS_MAX_CNAME_LEN]; - int rr_len; - struct dns_data_context data_context; + int ret; + int qtype = 0; + int qclass = 0; + int ttl = 0; + char domain[DNS_MAX_CNAME_LEN]; + int rr_len; + struct dns_data_context data_context; - data_context.data = rrs->data; - data_context.ptr = rrs->data; - data_context.maxsize = rrs->len; + data_context.data = rrs->data; + data_context.ptr = rrs->data; + data_context.maxsize = rrs->len; - ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); + if (ret < 0) { + return -1; + } - if (rr_len != DNS_RR_AAAA_LEN) { - return -1; - } + if (rr_len != DNS_RR_AAAA_LEN) { + return -1; + } - ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, DNS_RR_AAAA_LEN); - if (ret < 0) { - return -1; - } + ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, DNS_RR_AAAA_LEN); + if (ret < 0) { + return -1; + } - if (_dns_left_len(context) < DNS_RR_AAAA_LEN) { - return -1; - } + if (_dns_left_len(context) < DNS_RR_AAAA_LEN) { + return -1; + } - memcpy(context->ptr, rrs->data, DNS_RR_AAAA_LEN); - context->ptr += DNS_RR_AAAA_LEN; + memcpy(context->ptr, rrs->data, DNS_RR_AAAA_LEN); + context->ptr += DNS_RR_AAAA_LEN; - return 0; + return 0; } int _dns_decode_qd(struct dns_context *context) { - struct dns_packet *packet = context->packet; - int len; - int qtype = 0; - int qclass = 0; - char domain[DNS_MAX_CNAME_LEN]; + struct dns_packet *packet = context->packet; + int len; + int qtype = 0; + int qclass = 0; + char domain[DNS_MAX_CNAME_LEN]; - len = _dns_decode_qr_head(context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass); - if (len < 0) { - return -1; - } + len = _dns_decode_qr_head(context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass); + if (len < 0) { + return -1; + } - len = dns_add_domain(packet, domain, qtype, qclass); - if (len < 0) { - return -1; - } + len = dns_add_domain(packet, domain, qtype, qclass); + if (len < 0) { + return -1; + } - return 0; + return 0; } int _dns_decode_an(struct dns_context *context) { - int ret; - int qtype = 0; - int qclass = 0; - int ttl; - int rr_len = 0; - char domain[DNS_MAX_CNAME_LEN]; - struct dns_packet *packet = context->packet; + int ret; + int qtype = 0; + int qclass = 0; + int ttl; + int rr_len = 0; + char domain[DNS_MAX_CNAME_LEN]; + struct dns_packet *packet = context->packet; - ret = _dns_decode_rr_head(context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); - if (ret < 0) { - return -1; - } + ret = _dns_decode_rr_head(context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); + if (ret < 0) { + return -1; + } - switch (qtype) { - case DNS_T_CNAME: { - char cname[DNS_MAX_CNAME_LEN]; - ret = _dns_decode_CNAME(context, cname, DNS_MAX_CNAME_LEN); - if (ret < 0) { - return -1; - } + switch (qtype) { + case DNS_T_CNAME: { + char cname[DNS_MAX_CNAME_LEN]; + ret = _dns_decode_CNAME(context, cname, DNS_MAX_CNAME_LEN); + if (ret < 0) { + return -1; + } - ret = dns_add_CNAME(packet, domain, ttl, cname); - if (ret < 0) { - return -1; - } - } break; - case DNS_T_A: { - unsigned char addr[DNS_RR_A_LEN]; - ret = _dns_decode_A(context, addr); - if (ret < 0) { - return -1; - } + ret = dns_add_CNAME(packet, domain, ttl, cname); + if (ret < 0) { + return -1; + } + } break; + case DNS_T_A: { + unsigned char addr[DNS_RR_A_LEN]; + ret = _dns_decode_A(context, addr); + if (ret < 0) { + return -1; + } - ret = dns_add_A(packet, domain, ttl, addr); - if (ret < 0) { - return -1; - } - } break; - case DNS_T_AAAA: { - unsigned char addr[DNS_RR_AAAA_LEN]; - ret = _dns_decode_AAAA(context, addr); - if (ret < 0) { - return -1; - } + ret = dns_add_A(packet, domain, ttl, addr); + if (ret < 0) { + return -1; + } + } break; + case DNS_T_AAAA: { + unsigned char addr[DNS_RR_AAAA_LEN]; + ret = _dns_decode_AAAA(context, addr); + if (ret < 0) { + return -1; + } - ret = dns_add_AAAA(packet, domain, ttl, addr); - if (ret < 0) { - return -1; - } - } break; - default: - context->ptr += rr_len; - break; - } + ret = dns_add_AAAA(packet, domain, ttl, addr); + if (ret < 0) { + return -1; + } + } break; + default: + context->ptr += rr_len; + break; + } - return 0; + return 0; } int _dns_encode_qd(struct dns_context *context, struct dns_rrs *rrs) { - int ret; - int qtype = 0; - int qclass = 0; - char domain[DNS_MAX_CNAME_LEN]; - struct dns_data_context data_context; + int ret; + int qtype = 0; + int qclass = 0; + char domain[DNS_MAX_CNAME_LEN]; + struct dns_data_context data_context; - data_context.data = rrs->data; - data_context.ptr = rrs->data; - data_context.maxsize = rrs->len; + data_context.data = rrs->data; + data_context.ptr = rrs->data; + data_context.maxsize = rrs->len; - ret = _dns_get_qr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass); - if (ret < 0) { - return -1; - } + ret = _dns_get_qr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass); + if (ret < 0) { + return -1; + } - ret = _dns_encode_qr_head(context, domain, qtype, qclass); - if (ret < 0) { - return -1; - } + ret = _dns_encode_qr_head(context, domain, qtype, qclass); + if (ret < 0) { + return -1; + } - return 0; + return 0; } int _dns_encode_an(struct dns_context *context, struct dns_rrs *rrs) { - int ret; - switch (rrs->type) { - case DNS_T_A: { - ret = _dns_encode_A(context, rrs); - if (ret < 0) { - return -1; - } - } break; - case DNS_T_AAAA: - ret = _dns_encode_AAAA(context, rrs); - if (ret < 0) { - return -1; - } - break; - default: - break; - } + int ret; + switch (rrs->type) { + case DNS_T_A: { + ret = _dns_encode_A(context, rrs); + if (ret < 0) { + return -1; + } + } break; + case DNS_T_AAAA: + ret = _dns_encode_AAAA(context, rrs); + if (ret < 0) { + return -1; + } + break; + default: + break; + } - return 0; + return 0; } int _dns_decode_body(struct dns_context *context) { - struct dns_packet *packet = context->packet; - struct dns_head *head = &packet->head; - int i = 0; - int ret = 0; + struct dns_packet *packet = context->packet; + struct dns_head *head = &packet->head; + int i = 0; + int ret = 0; - for (i = 0; i < head->qdcount; i++) { - ret = _dns_decode_qd(context); - if (ret < 0) { - return -1; - } - head->qdcount--; - } + for (i = 0; i < head->qdcount; i++) { + ret = _dns_decode_qd(context); + if (ret < 0) { + return -1; + } + head->qdcount--; + } - for (i = 0; i < head->ancount; i++) { - ret = _dns_decode_an(context); - if (ret < 0) { - return -1; - } - head->ancount--; - } + for (i = 0; i < head->ancount; i++) { + ret = _dns_decode_an(context); + if (ret < 0) { + return -1; + } + head->ancount--; + } - return 0; + return 0; } int _dns_encode_body(struct dns_context *context) { - struct dns_packet *packet = context->packet; - struct dns_head *head = &packet->head; - int i = 0; - int len = 0; - struct dns_rrs *rrs; - int count; + struct dns_packet *packet = context->packet; + struct dns_head *head = &packet->head; + int i = 0; + int len = 0; + struct dns_rrs *rrs; + int count; - rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &count); - head->qdcount = count; - for (i = 0; i < count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) { - len = _dns_encode_qd(context, rrs); - if (len < 0) { - return -1; - } - } + rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &count); + head->qdcount = count; + for (i = 0; i < count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) { + len = _dns_encode_qd(context, rrs); + if (len < 0) { + return -1; + } + } - rrs = dns_get_rrs_start(packet, DNS_RRS_AN, &count); - head->ancount = count; - for (i = 0; i < count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) { - len = _dns_encode_an(context, rrs); - if (len < 0) { - return -1; - } - } + rrs = dns_get_rrs_start(packet, DNS_RRS_AN, &count); + head->ancount = count; + for (i = 0; i < count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) { + len = _dns_encode_an(context, rrs); + if (len < 0) { + return -1; + } + } - return 0; + return 0; } int dns_packet_init(struct dns_packet *packet, int size, struct dns_head *head) { - struct dns_head *init_head = &packet->head; - memset(packet, 0, size); - packet->size = size; - init_head->id = head->id; - init_head->qr = head->qr; - init_head->opcode = head->opcode; - init_head->aa = head->aa; - init_head->tc = 0; - init_head->rd = head->rd; - init_head->ra = head->ra; - init_head->rcode = head->rcode; - packet->questions = DNS_RR_END; - packet->answers = DNS_RR_END; - packet->nameservers = DNS_RR_END; - packet->additional = DNS_RR_END; + struct dns_head *init_head = &packet->head; + memset(packet, 0, size); + packet->size = size; + init_head->id = head->id; + init_head->qr = head->qr; + init_head->opcode = head->opcode; + init_head->aa = head->aa; + init_head->tc = 0; + init_head->rd = head->rd; + init_head->ra = head->ra; + init_head->rcode = head->rcode; + packet->questions = DNS_RR_END; + packet->answers = DNS_RR_END; + packet->nameservers = DNS_RR_END; + packet->additional = DNS_RR_END; - return 0; + return 0; } int dns_decode(struct dns_packet *packet, int maxsize, unsigned char *data, int size) { - struct dns_head *head = &packet->head; - struct dns_context context; - int ret = 0; + struct dns_head *head = &packet->head; + struct dns_context context; + int ret = 0; - memset(&context, 0, sizeof(context)); - memset(packet, 0, sizeof(*packet)); + memset(&context, 0, sizeof(context)); + memset(packet, 0, sizeof(*packet)); - context.data = data; - context.packet = packet; - context.ptr = data; - context.maxsize = size; + context.data = data; + context.packet = packet; + context.ptr = data; + context.maxsize = size; - dns_packet_init(packet, maxsize, head); - ret = _dns_decode_head(&context); - if (ret < 0) { - return -1; - } + dns_packet_init(packet, maxsize, head); + ret = _dns_decode_head(&context); + if (ret < 0) { + return -1; + } - ret = _dns_decode_body(&context); - if (ret < 0) { - return -1; - } + ret = _dns_decode_body(&context); + if (ret < 0) { + return -1; + } - return 0; + return 0; } int dns_encode(unsigned char *data, int size, struct dns_packet *packet) { - int ret = 0; - struct dns_context context; + int ret = 0; + struct dns_context context; - memset(&context, 0, sizeof(context)); - context.data = data; - context.packet = packet; - context.ptr = data; - context.maxsize = size; + memset(&context, 0, sizeof(context)); + context.data = data; + context.packet = packet; + context.ptr = data; + context.maxsize = size; - ret = _dns_encode_head(&context); - if (ret < 0) { - return -1; - } + ret = _dns_encode_head(&context); + if (ret < 0) { + return -1; + } - ret = _dns_encode_body(&context); - if (ret < 0) { - return -1; - } + ret = _dns_encode_body(&context); + if (ret < 0) { + return -1; + } - return context.ptr - context.data; + return context.ptr - context.data; }