re/src/dns/hdr.c
2012-08-16 08:43:50 +00:00

137 lines
3.1 KiB
C

/**
* @file dns/hdr.c DNS header encoding
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_fmt.h>
#include <re_list.h>
#include <re_mbuf.h>
#include <re_net.h>
#include <re_dns.h>
enum {
QUERY_RESPONSE = 15,
OPCODE = 11,
AUTH_ANSWER = 10,
TRUNCATED = 9,
RECURSION_DESIRED = 8,
RECURSION_AVAILABLE = 7,
ZERO = 4
};
/**
* Encode a DNS header
*
* @param mb Memory buffer to encode header into
* @param hdr DNS header
*
* @return 0 if success, otherwise errorcode
*/
int dns_hdr_encode(struct mbuf *mb, const struct dnshdr *hdr)
{
uint16_t flags = 0;
int err = 0;
if (!mb || !hdr)
return EINVAL;
flags |= hdr->qr <<QUERY_RESPONSE;
flags |= hdr->opcode <<OPCODE;
flags |= hdr->aa <<AUTH_ANSWER;
flags |= hdr->tc <<TRUNCATED;
flags |= hdr->rd <<RECURSION_DESIRED;
flags |= hdr->ra <<RECURSION_AVAILABLE;
flags |= hdr->z <<ZERO;
flags |= hdr->rcode;
err |= mbuf_write_u16(mb, htons(hdr->id));
err |= mbuf_write_u16(mb, htons(flags));
err |= mbuf_write_u16(mb, htons(hdr->nq));
err |= mbuf_write_u16(mb, htons(hdr->nans));
err |= mbuf_write_u16(mb, htons(hdr->nauth));
err |= mbuf_write_u16(mb, htons(hdr->nadd));
return err;
}
/**
* Decode a DNS header from a memory buffer
*
* @param mb Memory buffer to decode header from
* @param hdr DNS header (output)
*
* @return 0 if success, otherwise errorcode
*/
int dns_hdr_decode(struct mbuf *mb, struct dnshdr *hdr)
{
uint16_t flags = 0;
if (!mb || !hdr || (mbuf_get_left(mb) < DNS_HEADER_SIZE))
return EINVAL;
hdr->id = ntohs(mbuf_read_u16(mb));
flags = ntohs(mbuf_read_u16(mb));
hdr->qr = 0x1 & (flags >> QUERY_RESPONSE);
hdr->opcode = 0xf & (flags >> OPCODE);
hdr->aa = 0x1 & (flags >> AUTH_ANSWER);
hdr->tc = 0x1 & (flags >> TRUNCATED);
hdr->rd = 0x1 & (flags >> RECURSION_DESIRED);
hdr->ra = 0x1 & (flags >> RECURSION_AVAILABLE);
hdr->z = 0x7 & (flags >> ZERO);
hdr->rcode = 0xf & (flags >> 0);
hdr->nq = ntohs(mbuf_read_u16(mb));
hdr->nans = ntohs(mbuf_read_u16(mb));
hdr->nauth = ntohs(mbuf_read_u16(mb));
hdr->nadd = ntohs(mbuf_read_u16(mb));
return 0;
}
/**
* Get the string of a DNS opcode
*
* @param opcode DNS opcode
*
* @return Opcode string
*/
const char *dns_hdr_opcodename(uint8_t opcode)
{
switch (opcode) {
case DNS_OPCODE_QUERY: return "QUERY";
case DNS_OPCODE_IQUERY: return "IQUERY";
case DNS_OPCODE_STATUS: return "STATUS";
case DNS_OPCODE_NOTIFY: return "NOTIFY";
default: return "??";
}
}
/**
* Get the string of a DNS response code
*
* @param rcode Response code
*
* @return Response code string
*/
const char *dns_hdr_rcodename(uint8_t rcode)
{
switch (rcode) {
case DNS_RCODE_OK: return "OK";
case DNS_RCODE_FMT_ERR: return "Format Error";
case DNS_RCODE_SRV_FAIL: return "Server Failure";
case DNS_RCODE_NAME_ERR: return "Name Error";
case DNS_RCODE_NOT_IMPL: return "Not Implemented";
case DNS_RCODE_REFUSED: return "Refused";
case DNS_RCODE_NOT_AUTH: return "Server Not Authoritative for zone";
default: return "??";
}
}