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

Fixes - 512B w/o EDNS + TC bit

- Server was sending responses larger than 512B even if client did
  not advertise EDNS.
- Now using the given buffer for the packet's wireformat - should
  avoid some unnecessary mallocs.
- Setting TC bit in wireformat was missing.
parent 51ec9940
No related branches found
No related tags found
No related merge requests found
......@@ -41,7 +41,7 @@
/*! \brief Maximum UDP payload with EDNS enabled. */
static const uint16_t MAX_UDP_PAYLOAD_EDNS = 4096;
/*! \brief Maximum UDP payload with EDNS disabled. */
static const uint16_t MAX_UDP_PAYLOAD = 512;
static const uint16_t MAX_UDP_PAYLOAD = 500;
/*! \brief Maximum size of one AXFR response packet. */
static const uint16_t MAX_AXFR_PAYLOAD = 65535;
/*! \brief Supported EDNS version. */
......@@ -1361,7 +1361,7 @@ static inline int ns_referral(const knot_node_t *node,
}
/*! \todo What if there is no NSEC3? */
} else {
knot_rrset_t *nsec = knot_node_rrset(
const knot_rrset_t *nsec = knot_node_rrset(
node, KNOT_RRTYPE_NSEC);
if (nsec) {
/*! \todo Check return value? */
......@@ -1867,7 +1867,14 @@ static int ns_response_to_wire(knot_packet_t *resp, uint8_t *wire,
return NS_ERR_SERVFAIL;
}
memcpy(wire, rwire, rsize);
if (rwire != wire) {
debug_knot_ns("Wire format reallocated, copying to place for "
"wire.\n");
memcpy(wire, rwire, rsize);
} else {
debug_knot_ns("Using the same space or wire format.\n");
}
*wire_size = rsize;
//free(rwire);
......@@ -1894,8 +1901,7 @@ static int ns_axfr_send_and_clear(knot_ns_xfr_t *xfr)
// Transform the packet into wire format
debug_knot_ns("Converting response to wire format..\n");
size_t real_size = xfr->wire_size;
if (ns_response_to_wire(xfr->response, xfr->wire, &real_size)
!= 0) {
if (ns_response_to_wire(xfr->response, xfr->wire, &real_size) != 0) {
return NS_ERR_SERVFAIL;
// // send back SERVFAIL (as this is our problem)
// ns_error_response(nameserver,
......@@ -2319,8 +2325,12 @@ static int ns_ixfr(knot_ns_xfr_t *xfr)
static int knot_ns_prepare_response(knot_nameserver_t *nameserver,
knot_packet_t *query, knot_packet_t **resp,
uint8_t *response_wire,
size_t max_size)
{
assert(response_wire != NULL);
assert(max_size >= 500);
// initialize response packet structure
*resp = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
if (*resp == NULL) {
......@@ -2328,15 +2338,17 @@ static int knot_ns_prepare_response(knot_nameserver_t *nameserver,
return KNOT_ENOMEM;
}
int ret = knot_packet_set_max_size(*resp, max_size);
//int ret = knot_packet_set_max_size(*resp, max_size);
(*resp)->wireformat = response_wire;;
(*resp)->max_size = max_size;
if (ret != KNOT_EOK) {
debug_knot_ns("Failed to init response structure.\n");
knot_packet_free(resp);
return ret;
}
// if (ret != KNOT_EOK) {
// debug_knot_ns("Failed to init response structure.\n");
// knot_packet_free(resp);
// return ret;
// }
ret = knot_response_init_from_query(*resp, query);
int ret = knot_response_init_from_query(*resp, query);
if (ret != KNOT_EOK) {
debug_knot_ns("Failed to init response structure.\n");
......@@ -2562,7 +2574,8 @@ int knot_ns_answer_normal(knot_nameserver_t *nameserver, knot_packet_t *query,
int ret;
knot_packet_t *response;
ret = knot_ns_prepare_response(nameserver, query, &response, *rsize);
ret = knot_ns_prepare_response(nameserver, query, &response,
response_wire, *rsize);
if (ret != KNOT_EOK) {
knot_ns_error_response(nameserver, knot_packet_id(query),
KNOT_RCODE_SERVFAIL, response_wire,
......@@ -2598,17 +2611,35 @@ int knot_ns_answer_normal(knot_nameserver_t *nameserver, knot_packet_t *query,
// set the OPT RR to the response
if (knot_query_edns_supported(query)) {
ret = knot_response_add_opt(response, nameserver->opt_rr, 0);
/*! \todo API. */
knot_packet_set_max_size(response, knot_edns_get_payload(
&query->opt_rr));
ret = knot_response_add_opt(response, nameserver->opt_rr, 1);
if (ret != KNOT_EOK) {
debug_knot_ns("Failed to set OPT RR to the response"
": %s\n",knot_strerror(ret));
} else {
// copy the DO bit from the query
if(knot_query_dnssec_requested(query)) {
/*! \todo API for this. */
knot_edns_set_do(&response->opt_rr);
}
}
// copy the DO bit from the query
if(knot_query_dnssec_requested(query)) {
/*! \todo API for this. */
knot_edns_set_do(&response->opt_rr);
} else {
debug_knot_ns("Setting max size to %u.\n", MAX_UDP_PAYLOAD);
ret = knot_packet_set_max_size(response, MAX_UDP_PAYLOAD);
if (ret != KNOT_EOK) {
debug_knot_ns("Failed to set max size to %u\n",
MAX_UDP_PAYLOAD);
knot_ns_error_response_full(nameserver, response,
KNOT_RCODE_SERVFAIL,
response_wire, rsize);
return KNOT_EOK;
}
}
debug_knot_ns("Response max size: %zu\n", response->max_size);
ret = ns_answer(zonedb, response);
if (ret != 0) {
......@@ -2667,21 +2698,23 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
return res;
}
int ret = knot_packet_set_max_size(response, xfr->wire_size);
if (ret != KNOT_EOK) {
debug_knot_ns("Failed to init response structure.\n");
/*! \todo xfr->wire is not NULL, will fail on assert! */
knot_ns_error_response(nameserver, xfr->query->header.id,
KNOT_RCODE_SERVFAIL, xfr->wire,
&xfr->wire_size);
int res = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
knot_packet_free(&response);
return res;
}
//int ret = knot_packet_set_max_size(response, xfr->wire_size);
response->wireformat = xfr->wire;
response->max_size = xfr->wire_size;
// if (ret != KNOT_EOK) {
// debug_knot_ns("Failed to init response structure.\n");
// /*! \todo xfr->wire is not NULL, will fail on assert! */
// knot_ns_error_response(nameserver, xfr->query->header.id,
// KNOT_RCODE_SERVFAIL, xfr->wire,
// &xfr->wire_size);
// int res = xfr->send(xfr->session, &xfr->addr, xfr->wire,
// xfr->wire_size);
// knot_packet_free(&response);
// return res;
// }
ret = knot_response_init_from_query(response, xfr->query);
int ret = knot_response_init_from_query(response, xfr->query);
if (ret != KNOT_EOK) {
debug_knot_ns("Failed to init response structure.\n");
......@@ -3023,8 +3056,9 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
assert(knot_packet_is_query(query));
knot_packet_t *response;
/*! \todo It is OK not to use the given size?? */
int ret = knot_ns_prepare_response(nameserver, query, &response,
*rsize);
response_wire, *rsize);
if (ret != KNOT_EOK) {
knot_ns_error_response(nameserver, knot_packet_id(query),
KNOT_RCODE_SERVFAIL, response_wire,
......
......@@ -774,7 +774,9 @@ DEBUG_KNOT_RESPONSE(
"size of response: %zu\n\n", size, rrs,
resp->size);
} else if (tc) {
debug_knot_response("Setting TC bit.\n");
knot_wire_flags_set_tc(&resp->header.flags1);
knot_wire_set_tc(resp->wireformat);
}
return rrs;
......@@ -950,6 +952,8 @@ int knot_response_add_opt(knot_packet_t *resp,
// set max size (less is OK)
if (override_max_size) {
debug_knot_response("Overriding max size to: %u\n",
resp->opt_rr.payload);
return knot_packet_set_max_size(resp, resp->opt_rr.payload);
//resp->max_size = resp->opt_rr.payload;
}
......
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