/*
 * Copyright (c) 2016 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dns_pack.h"

#include <string.h>

static inline size_t dns_strlen(char *str)
{
	if (str == NULL) {
		return 0;
	}
	return strlen(str);
}

int dns_msg_pack_qname(int *len, uint8_t *buf, int size, char *domain_name)
{
	int lb_index;
	int lb_start;
	int lb_size;
	size_t i;

	lb_start = 0;
	lb_index = 1;
	lb_size = 0;

	/* traverse the domain name str, including the null-terminator :) */
	for (i = 0; i < dns_strlen(domain_name) + 1; i++) {
		if (lb_index >= size) {
			return -ENOMEM;
		}

		switch (domain_name[i]) {
		default:
			buf[lb_index] = domain_name[i];
			lb_size += 1;
			break;
		case '.':
			buf[lb_start] = lb_size;
			lb_size = 0;
			lb_start = lb_index;
			break;
		case '\0':
			buf[lb_start] = lb_size;
			buf[lb_index] = 0;
			break;
		}
		lb_index += 1;
	}

	*len = lb_index;
	return 0;
}

int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr)
{
	uint8_t *answer;
	int buf_size;
	int ptr;

	answer = dns_msg->msg + dns_msg->answer_offset;

	/* See RFC-1035 to find out why 63	*/
	if (answer[0] < 63) {
		return -ENOMEM;
	}

	/* Recovery of the pointer value	*/
	ptr = (((answer[0] & 63) << 8) + answer[1]);
	if (ptr != dname_ptr) {
		return -ENOMEM;
	}

	/*
	 * We need to be sure this buffer has enough space
	 * to parse the answer.
	 *
	 * size: dname_size + type + class + ttl + rdlength + rdata
	 *            2     +   2  +   2   +  4  +     2    +  ?
	 *
	 * So, answer size >= 12
	 *
	 * See RFC-1035 4.1.3. Resource record format
	 */
	buf_size = dns_msg->msg_size - dns_msg->answer_offset;
	if (buf_size < 12) {
		return -ENOMEM;
	}

	/* Only answers of type Internet.
	 * Here we use 2 as an offset because a ptr uses only 2 bytes.
	 */
	if (dns_answer_class(2, answer) != DNS_CLASS_IN) {
		return -EINVAL;
	}

	switch (dns_response_type(2, answer)) {
	case DNS_RR_TYPE_A:
	case DNS_RR_TYPE_AAAA:
		dns_msg->response_type = DNS_RESPONSE_IP;
		dns_msg->response_position = dns_msg->answer_offset + 12;
		dns_msg->response_length = dns_unpack_answer_rdlength(2,
								      answer);

		return 0;

	case DNS_RR_TYPE_CNAME:

		dns_msg->response_type = DNS_RESPONSE_CNAME_NO_IP;
		dns_msg->response_position = dns_msg->answer_offset + 12;
		dns_msg->response_length = dns_unpack_answer_rdlength(2,
								      answer);

		return 0;

	default:
		/* malformed dns answer */
		return -EINVAL;
	}

	return 0;
}

int dns_unpack_response_header(struct dns_msg_t *msg, int src_id)
{
	uint8_t *dns_header;
	int size;
	int qdcount;
	int ancount;
	int rcode;

	dns_header = msg->msg;
	size = msg->msg_size;

	if (size < DNS_MSG_HEADER_SIZE) {
		return -ENOMEM;
	}

	if (dns_unpack_header_id(dns_header) != src_id) {
		return -EINVAL;
	}

	if (dns_header_qr(dns_header) != DNS_RESPONSE) {
		return -EINVAL;
	}

	if (dns_header_opcode(dns_header) != DNS_QUERY) {
		return -EINVAL;
	}

	if (dns_header_z(dns_header) != 0) {
		return -EINVAL;
	}

	rcode = dns_header_rcode(dns_header);
	switch (rcode) {
	case DNS_HEADER_NOERROR:
		break;
	default:
		return rcode;

	}

	qdcount = dns_unpack_header_qdcount(dns_header);
	ancount = dns_unpack_header_ancount(dns_header);
	if (qdcount < 1 || ancount < 1) {
		return -EINVAL;
	}

	return 0;
}

static int dns_msg_pack_query_header(uint8_t *buf, int size, uint16_t id)
{
	if (size < DNS_MSG_HEADER_SIZE) {
		return -ENOMEM;
	}

	*(uint16_t *)(buf +  0) = sys_cpu_to_be16(id);

	/* RD = 1, TC = 0, AA = 0, Opcode = 0, QR = 0 <-> 0x01 (1B)
	 * RCode = 0, Z = 0, RA = 0		      <-> 0x00 (1B)
	 *
	 * QDCOUNT = 1				      <-> 0x0001 (2B)
	 */

	*(buf + 2) = 0x01;
	*(buf + 3) = 0x00;
	*(uint16_t *)(buf + 4) = sys_cpu_to_be16(1);
	*(uint32_t *)(buf +  6) = 0;	/* ANCOUNT and NSCOUNT = 0	*/
	*(uint16_t *)(buf +  10) = 0;   /* ARCOUNT = 0			*/

	return 0;
}

int dns_msg_pack_query(struct app_buf_t *buf, char *domain_name,
			uint16_t id, enum dns_rr_type qtype)
{
	int qname_len;
	int offset;
	int rc;

	rc = dns_msg_pack_query_header(buf->buf, buf->size, id);
	if (rc != 0) {
		return rc;
	}

	offset = DNS_MSG_HEADER_SIZE;

	rc = dns_msg_pack_qname(&qname_len, buf->buf + offset,
				buf->size - offset, domain_name);
	if (rc != 0) {
		return rc;
	}

	offset += qname_len;

	/* 4Bytes required: QType: (2B), QClass (2B)	*/
	if (offset + 4 > buf->size) {
		return rc;
	}
	/* QType */
	*(uint16_t *)(buf->buf + offset + 0) = sys_cpu_to_be16(qtype);
	/* QClass */
	*(uint16_t *)(buf->buf + offset + 2) = sys_cpu_to_be16(DNS_CLASS_IN);

	buf->length = offset + 4;

	return 0;
}

int dns_find_null(int *qname_size, uint8_t *buf, int size)
{
	*qname_size = 0;
	while (*qname_size < size) {
		if (buf[(*qname_size)++] == 0x00) {
			return 0;
		}
	}

	return -ENOMEM;
}

int dns_unpack_response_query(struct dns_msg_t *dns_msg)
{
	uint8_t *dns_query;
	uint8_t *buf;
	int remaining_size;
	int qname_size;
	int offset;
	int rc;

	dns_msg->query_offset = DNS_MSG_HEADER_SIZE;
	dns_query = dns_msg->msg + dns_msg->query_offset;
	remaining_size = dns_msg->msg_size - dns_msg->query_offset;

	rc = dns_find_null(&qname_size, dns_query, remaining_size);
	if (rc != 0) {
		return rc;
	}

	/* header already parsed + qname size */
	offset = dns_msg->query_offset + qname_size;
	/* 4 bytes more for qtype and qclass */
	offset += 4;
	if (offset > dns_msg->msg_size) {
		return -ENOMEM;
	}

	buf = dns_query + qname_size;
	if (dns_unpack_query_qtype(buf) != DNS_RR_TYPE_A &&
	    dns_unpack_query_qtype(buf) != DNS_RR_TYPE_AAAA) {
		return -EINVAL;
	}

	if (dns_unpack_query_qclass(buf) != DNS_CLASS_IN) {
		return -EINVAL;
	}

	dns_msg->answer_offset = dns_msg->query_offset + qname_size + 4;

	return 0;
}
