137 lines
3.1 KiB
C
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 "??";
|
|
}
|
|
}
|