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

ns_answer_request() returning error response.

ns_create_response() divided into ns_create_empty_response()
  (empty response may be used as an error response) and
  ns_fill_response().
Added another sample zone as ldns had problems parsing the bogus25
  zone.
parent 00fabb98
No related branches found
No related tags found
No related merge requests found
$TTL 86400
bogus25.com. IN SOA ns1.bogus25.com. support.bogus25.com. (
bogus25.com. IN SOA ns1.bogus25.com. support.bogus25.com. (
20010923; Serial
10800 ; Refresh after 3hrs
3600 ; Retry after 1 hr
......
$ORIGIN example.com. ; designates the start of this zone file in the name space
$TTL 1h ; The default expiration time of a resource record without its own TTL value
example.com. IN SOA ns.example.com. username.example.com. (
2007120710 ; serial number of this zone file
1d ; slave refresh (1 day)
1d ; slave retry time in case of a problem (1 day)
4w ; slave expiration time (4 weeks)
1h ; minimum caching time in case of failed lookups (1 hour)
)
example.com. NS ns ; ns.example.com is the nameserver for example.com
example.com. NS ns.somewhere.com. ; ns.somewhere.com is a backup nameserver for example.com
example.com. MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com
@ MX 20 mail2.example.com. ; Similar to above line, but using "@" to say "use $ORIGIN"
@ MX 50 mail3 ; Similar to above line, but using a host within this domain
example.com. A 10.0.0.1 ; ip address for "example.com"
ns A 10.0.0.2 ; ip address for "ns.example.com". Since there is no "." after ns, $ORIGIN is attached
www CNAME ns ; "www.example.com" is an alias for "ns.example.com"
wwwtest CNAME www ; "wwwtest.example.com" is another alias for "www.example.com"
mail A 10.0.0.3 ; ip address for "mail.example.com", any MX record host must be
......@@ -9,9 +9,9 @@
//#define CUCKOO_DEBUG
//#define CUCKOO_DEBUG_HASH
//#define ZP_DEBUG
#define NS_DEBUG
#define ZDB_DEBUG
#define ZP_DEBUG_PARSE
//#define NS_DEBUG
//#define ZDB_DEBUG
//#define ZP_DEBUG_PARSE
#ifdef CUTE_DEBUG
#define debug_server(msg...) log_msg(LOG_DEBUG, msg)
......
......@@ -25,8 +25,7 @@ ns_nameserver *ns_create( zdb_database *database )
/*----------------------------------------------------------------------------*/
ldns_pkt *ns_create_response( ldns_pkt *query, ldns_rr_list *answer,
ldns_rr_list *authority, ldns_rr_list *additional )
ldns_pkt *ns_create_empty_response( ldns_pkt *query )
{
ldns_pkt *response = ldns_pkt_clone(query);
if (response == NULL) {
......@@ -35,6 +34,23 @@ ldns_pkt *ns_create_response( ldns_pkt *query, ldns_rr_list *answer,
ldns_pkt_set_aa(response, 1);
ldns_pkt_set_qr(response, 1);
ldns_pkt_set_answer(response, NULL);
ldns_pkt_set_ancount(response, 0);
ldns_pkt_set_authority(response, NULL);
ldns_pkt_set_nscount(response, 0);
ldns_pkt_set_additional(response, NULL);
ldns_pkt_set_arcount(response, 0);
return response;
}
/*----------------------------------------------------------------------------*/
void ns_fill_response( ldns_pkt *response, ldns_rr_list *answer,
ldns_rr_list *authority, ldns_rr_list *additional )
{
ldns_pkt_set_answer(response, ldns_rr_list_clone(answer));
ldns_pkt_set_ancount(response, ldns_rr_list_rr_count(answer));
......@@ -51,8 +67,6 @@ ldns_pkt *ns_create_response( ldns_pkt *query, ldns_rr_list *answer,
ldns_pkt_set_arcount(response, (additional == NULL)
? 0
: ldns_rr_list_rr_count(additional));
return response;
}
/*----------------------------------------------------------------------------*/
......@@ -66,15 +80,25 @@ int ns_answer_request( ns_nameserver *nameserver, const uint8_t *query_wire,
ldns_status s = LDNS_STATUS_OK;
ldns_pkt *query;
if ((s = ldns_wire2pkt(&query, query_wire, qsize)) != LDNS_STATUS_OK) {
log_error("Error while parsing query.\nldns returned: %s\n",
log_info("Error while parsing query.\nldns returned: %s\n",
ldns_get_errorstr_by_id(s));
// TODO: create error response
// malformed question => ignore
// TODO: should somehow return FORMERR ??? we would need to copy the
// wire format of the query and just set the proper RCODE, AA and QR bit
return -1;
}
debug_ns("Query parsed:\n");
debug_ns("%s", ldns_pkt2str(query));
// prepare empty response (used as an error response as well)
ldns_pkt *response = ns_create_empty_response(query);
if (response == NULL) {
log_error("Error while creating response packet!\n");
ldns_pkt_free(query);
return -1;
}
rcu_read_lock();
// get the first question entry
......@@ -87,59 +111,50 @@ int ns_answer_request( ns_nameserver *nameserver, const uint8_t *query_wire,
ldns_rr_owner(question));
if (node == NULL) {
debug_ns("Name not found in the zone database.\n");
// TODO: create error response
ldns_pkt_free(query);
rcu_read_unlock();
return -1;
}
// get the appropriate RRSet
ldns_rr_list *answer = skip_find(node->rrsets,
(void *)ldns_rr_get_type(question));
if (answer == NULL) {
debug_ns("Requested RR TYPE not found in the node.\n");
// TODO: create error response
ldns_pkt_free(query);
rcu_read_unlock();
return -1;
}
// create response packet (RRs are copied)
ldns_pkt *response = ns_create_response(query, answer, NULL, NULL);
if (response == NULL) {
log_error("Error creating response packet.\n");
// TODO: create error response
ldns_pkt_free(query);
rcu_read_unlock();
return -1;
// return NXDOMAIN
ldns_pkt_set_rcode(response, LDNS_RCODE_NXDOMAIN);
} else {
// get the appropriate RRSet
ldns_rr_list *answer = skip_find(node->rrsets,
(void *)ldns_rr_get_type(question));
if (answer != NULL) {
// fill the response packet (RRs are copied)
ns_fill_response(response, answer, NULL, NULL);
// end of RCU read critical section (all data copied)
node = NULL;
}
// make sure proper RCODE is set
ldns_pkt_set_rcode(response, LDNS_RCODE_NOERROR);
// if not found, it means there is no RRSet for given type
// return "NODATA" response - i.e. empty with NOERROR RCODE
}
rcu_read_unlock();
ldns_pkt_free(query);
debug_ns("Created response packet:\n");
debug_ns("%s", ldns_pkt2str(response));
// end of RCU read critical section (all data copied)
node = NULL;
rcu_read_unlock();
// transform the packet into wire format
uint8_t *resp_wire = NULL;
size_t resp_size = 0;
if ((s = ldns_pkt2wire(&resp_wire, response, &resp_size))
!= LDNS_STATUS_OK) {
log_error("Error converting response packet to wire format.\n"
"ldns returned: %s\n", ldns_get_errorstr_by_id(s));
// TODO: create error response
ldns_pkt_free(query);
ldns_pkt_free(response); // watch out, this deletes also the RRs!!
// send nothing back
ldns_pkt_free(response);
return -1;
}
ldns_pkt_free(response);
if (resp_size > *rsize) {
debug_ns("Response in wire format longer than acceptable.\n");
// TODO: what about truncation???
// TODO: create error response
ldns_pkt_free(query);
ldns_pkt_free(response); // watch out, this deletes also the RRs!!
// TODO: truncation
assert(0);
return -1;
}
......
......@@ -56,6 +56,8 @@ ns_nameserver *ns_create( zdb_database *database );
* @param rsize Input: maximum acceptable size of the response. Output: real
* size of the response.
*
* @todo Truncation of the packet.
*
* @retval 0 if a valid response was created.
* @retval -1 if an error occured and the response is not valid.
*/
......
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