Skip to content
Snippets Groups Projects
Commit b10f883b authored by Lubos Slovak's avatar Lubos Slovak
Browse files

API for parsing query and type distinction.

- Added a separate function to nameserver to parse query and get
  its type.
- Added special type for query types to dnslib/consts.h.

WARNING: The rest of the API is not modified yet to support the
         pre-parsed query, so you must still call
         ns_answer_request() with the unparsed query.

refs #750, 749
parent 11d71b90
No related branches found
No related tags found
No related merge requests found
......@@ -27,6 +27,20 @@ typedef enum dnslib_opcode {
DNSLIB_OPCODE_OFFSET = 14
} dnslib_opcode_t;
/*!
* \brief Query types (internal use only).
*
* This type encompasses the different query types distinguished by both the
* OPCODE and the QTYPE.
*/
typedef enum dnslib_query {
DNSLIB_QUERY_NORMAL, /*!< Normal query. */
DNSLIB_QUERY_AXFR, /*!< Request for AXFR transfer. */
DNSLIB_QUERY_IXFR, /*!< Request for IXFR transfer. */
DNSLIB_QUERY_NOTIFY, /*!< NOTIFY query. */
DNSLIB_QUERY_UPDATE /*!< Dynamic update. */
} dnslib_query_t;
/*
* RCODEs
*/
......
......@@ -43,35 +43,6 @@ static const int NS_ERR_SERVFAIL = -999;
/*----------------------------------------------------------------------------*/
/* Private functions */
/*----------------------------------------------------------------------------*/
/*!
* \brief Prepares wire format of an error response using generic error template
* stored in the nameserver structure.
*
* The error response will not contain the Question section from the query, just
* a header with ID copied from the query and the given RCODE.
*
* \param nameserver Nameserver structure containing the error template.
* \param query_wire Wire format of the query.
* \param rcode RCODE to set in the response.
* \param response_wire Place for wire format of the response.
* \param rsize Size of the error response will be stored here.
*/
static inline void ns_error_response(ns_nameserver_t *nameserver,
const uint8_t *query_wire,
uint8_t rcode,
uint8_t *response_wire,
size_t *rsize)
{
memcpy(response_wire, nameserver->err_response,
nameserver->err_resp_size);
// copy ID of the query
memcpy(response_wire, query_wire, 2);
// set the RCODE
dnslib_packet_set_rcode(response_wire, rcode);
*rsize = nameserver->err_resp_size;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief Finds zone where to search for the QNAME.
......@@ -1850,6 +1821,84 @@ ns_nameserver_t *ns_create()
/*----------------------------------------------------------------------------*/
int ns_parse_query(const uint8_t *query_wire, size_t qsize,
dnslib_response_t *parsed, dnslib_query_t *type)
{
debug_ns("ns_answer_request() called with query size %zu.\n", qsize);
debug_ns_hex((char *)query_wire, qsize);
if (qsize < 2) {
return KNOT_EMALF;
}
// 1) create empty response
debug_ns("Parsing query using new dnslib structure...\n");
parsed = dnslib_response_new_empty(NULL);
if (parsed == NULL) {
log_answer_error("Error while creating response packet!\n");
return DNSLIB_RCODE_SERVFAIL;
}
int ret = 0;
// 2) parse the query
if ((ret = dnslib_response_parse_query(parsed, query_wire,
qsize)) != 0) {
log_answer_info("Error while parsing query, "
"dnslib error '%d'.\n",
ret);
dnslib_response_free(&parsed);
return DNSLIB_RCODE_FORMERR;
}
debug_ns("Query parsed.\n");
dnslib_response_dump(parsed);
// 3) determine the query type
switch (dnslib_response_opcode(parsed)) {
case DNSLIB_OPCODE_QUERY:
switch (dnslib_response_qtype(parsed)) {
case DNSLIB_RRTYPE_AXFR:
*type = DNSLIB_QUERY_AXFR;
break;
case DNSLIB_RRTYPE_IXFR:
*type = DNSLIB_QUERY_IXFR;
break;
default:
*type = DNSLIB_QUERY_NORMAL;
}
break;
case DNSLIB_OPCODE_NOTIFY:
*type = DNSLIB_QUERY_NOTIFY;
break;
case DNSLIB_OPCODE_UPDATE:
*type = DNSLIB_QUERY_UPDATE;
break;
default:
return DNSLIB_RCODE_NOTIMPL;
}
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
void ns_error_response(ns_nameserver_t *nameserver, const uint8_t *query_wire,
uint8_t rcode, uint8_t *response_wire, size_t *rsize)
{
memcpy(response_wire, nameserver->err_response,
nameserver->err_resp_size);
// copy ID of the query
memcpy(response_wire, query_wire, 2);
// set the RCODE
dnslib_packet_set_rcode(response_wire, rcode);
*rsize = nameserver->err_resp_size;
}
/*----------------------------------------------------------------------------*/
int ns_answer_request(ns_nameserver_t *nameserver, const uint8_t *query_wire,
size_t qsize, uint8_t *response_wire, size_t *rsize)
{
......
......@@ -25,6 +25,8 @@
#include "dnslib/zonedb.h"
#include "dnslib/edns.h"
#include "dnslib/response.h"
#include "dnslib/consts.h"
struct conf_t;
......@@ -54,6 +56,53 @@ typedef struct ns_nameserver {
*/
ns_nameserver_t *ns_create();
/*!
* \brief Parses the given query into the response structure and recognizes
* type of the query.
*
* Some query types are distinguished by OPCODE (NOTIFY, UPDATE, etc.), some
* by QTYPE (AXFR, IXFR). As these information are needed on the same layer
* to decide what to do with the query, the dnslib_query_t type is used for this
* purpose.
*
* \param query_wire Wire format of the query.
* \param qsize Size of the query in octets.
* \param parsed Response structure to be filled with the parsed query.
* \param type Type of the query.
*
* \retval KNOT_EOK
* \retval KNOT_EMALF if the query is totally unusable. Such query must be
* ignored.
* \retval DNSLIB_RCODE_SERVFAIL if there was some internal error. Call
* ns_error_response() with \a rcode set to this
* value to get proper error response.
* \retval DNSLIB_RCODE_FORMERR if the query was malformed, but can be used to
* construct an error response. Call
* ns_error_response() with \a rcode set to this
* value to get proper error response.
* \retval DNSLIB_RCODE_NOTIMPL if the query has an unsupported type. Call
* ns_error_response() with \a rcode set to this
* value to get proper error response.
*/
int ns_parse_query(const uint8_t *query_wire, size_t qsize,
dnslib_response_t *parsed, dnslib_query_t *type);
/*!
* \brief Prepares wire format of an error response using generic error template
* stored in the nameserver structure.
*
* The error response will not contain the Question section from the query, just
* a header with ID copied from the query and the given RCODE.
*
* \param nameserver Nameserver structure containing the error template.
* \param query_wire Wire format of the query.
* \param rcode RCODE to set in the response.
* \param response_wire Place for wire format of the response.
* \param rsize Size of the error response will be stored here.
*/
void ns_error_response(ns_nameserver_t *nameserver, const uint8_t *query_wire,
uint8_t rcode, uint8_t *response_wire, size_t *rsize);
/*!
* \brief Creates a response for the given query using the data of the name
* server.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment