}
goto send_reply;
}
- if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->scratchpad)) != 0) {
+ if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->env.cfg, c,
+ worker->scratchpad)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
r->cb = cb;
r->cb_arg = cb_arg;
r->edns = *edns;
- if(edns->opt_list_in || edns->opt_list_out || edns->opt_list_modules_out) {
- r->edns.opt_list_in = edns_opt_copy_region(edns->opt_list_in,
- s->s.region);
- if(!r->edns.opt_list_in)
- return 0;
- r->edns.opt_list_out = edns_opt_copy_region(edns->opt_list_out,
- s->s.region);
- if(!r->edns.opt_list_out)
- return 0;
- r->edns.opt_list_modules_out = edns_opt_copy_region(edns->opt_list_modules_out,
- s->s.region);
- if(!r->edns.opt_list_modules_out)
- return 0;
- }
+ if(edns->opt_list_in && !(r->edns.opt_list_in =
+ edns_opt_copy_region(edns->opt_list_in, s->s.region)))
+ return 0;
+ if(edns->opt_list_out && !(r->edns.opt_list_out =
+ edns_opt_copy_region(edns->opt_list_out, s->s.region)))
+ return 0;
+ if(edns->opt_list_modules_out && !(r->edns.opt_list_modules_out =
+ edns_opt_copy_region(edns->opt_list_modules_out, s->s.region)))
+ return 0;
r->qid = qid;
r->qflags = qflags;
r->next = s->cb_list;
return 0;
r->query_reply = *rep;
r->edns = *edns;
- if(edns->opt_list_in || edns->opt_list_out || edns->opt_list_modules_out) {
- r->edns.opt_list_in = edns_opt_copy_region(edns->opt_list_in,
- s->s.region);
- if(!r->edns.opt_list_in)
- return 0;
- r->edns.opt_list_out = edns_opt_copy_region(edns->opt_list_out,
- s->s.region);
- if(!r->edns.opt_list_out)
- return 0;
- r->edns.opt_list_modules_out = edns_opt_copy_region(edns->opt_list_modules_out,
- s->s.region);
- if(!r->edns.opt_list_modules_out)
- return 0;
- }
+ if(edns->opt_list_in && !(r->edns.opt_list_in =
+ edns_opt_copy_region(edns->opt_list_in, s->s.region)))
+ return 0;
+ if(edns->opt_list_out && !(r->edns.opt_list_out =
+ edns_opt_copy_region(edns->opt_list_out, s->s.region)))
+ return 0;
+ if(edns->opt_list_modules_out && !(r->edns.opt_list_modules_out =
+ edns_opt_copy_region(edns->opt_list_modules_out, s->s.region)))
+ return 0;
r->qid = qid;
r->qflags = qflags;
r->start_time = *s->s.env->now_tv;
* Routines for message parsing a packet buffer to a descriptive structure.
*/
#include "config.h"
+#include "util/config_file.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
+#include "util/netevent.h"
#include "util/storage/lookup3.h"
#include "util/regional.h"
#include "sldns/rrdef.h"
/** parse EDNS options from EDNS wireformat rdata */
static int
parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
- struct edns_data* edns, struct regional* region)
+ struct edns_data* edns, struct config_file* cfg, struct comm_point* c,
+ struct regional* region)
{
+ int keepalive;
+ uint8_t data[2]; /* For keepalive value */
+
/* while still more options, and have code+len to read */
/* ignores partial content (i.e. rdata len 3) */
while(rdata_len >= 4) {
rdata_len -= 4;
if(opt_len > rdata_len)
break; /* option code partial */
- if(!edns_opt_list_append(&edns->opt_list_in, opt_code, opt_len,
- rdata_ptr, region)) {
- log_err("out of memory");
- return 0;
+
+ /* handle parse time edns options here */
+ switch(opt_code) {
+ case LDNS_EDNS_NSID:
+ if (!cfg->nsid)
+ break;
+ if(!edns_opt_list_append(&edns->opt_list_out,
+ LDNS_EDNS_NSID, cfg->nsid_len,
+ cfg->nsid, region)) {
+ log_err("out of memory");
+ return 0;
+ }
+ break;
+
+ case LDNS_EDNS_KEEPALIVE:
+ /* To respond with a Keepalive option, the client
+ * connection must have received one message with a TCP
+ * Keepalive EDNS option, and that option must have 0
+ * length data. Subsequent messages sent on that
+ * connection will have a TCP Keepalive option.
+ */
+ if (!cfg->do_tcp_keepalive || c->type != comm_udp ||
+ !c->tcp_keepalive)
+ break;
+ keepalive = c->tcp_timeout_msec / 100;
+ data[0] = (uint8_t)((keepalive >> 8) & 0xff);
+ data[1] = (uint8_t)(keepalive & 0xff);
+ if(!edns_opt_list_append(&edns->opt_list_out,
+ LDNS_EDNS_KEEPALIVE,
+ sizeof(data), data, region)) {
+ log_err("out of memory");
+ return 0;
+ }
+ c->tcp_keepalive = 1;
+ break;
+
+ case LDNS_EDNS_PADDING:
+ if(!cfg->pad_responses || c->type != comm_tcp ||!c->ssl)
+ break;
+ if(!edns_opt_list_append(&edns->opt_list_out,
+ LDNS_EDNS_PADDING,
+ 0, NULL, region)) {
+ log_err("out of memory");
+ return 0;
+ }
+ edns->padding_block_size = cfg->pad_responses_block_size;
+ break;
+
+ default:
+ if(!edns_opt_list_append(&edns->opt_list_in,
+ opt_code, opt_len, rdata_ptr, region)) {
+ log_err("out of memory");
+ return 0;
+ }
+ break;
}
rdata_ptr += opt_len;
rdata_len -= opt_len;
/* take the options */
rdata_len = found->rr_first->size-2;
rdata_ptr = found->rr_first->ttl_data+6;
- if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
+ if(!parse_edns_options(rdata_ptr, rdata_len, edns, NULL, NULL, region))
return 0;
/* ignore rrsigs */
int
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
- struct regional* region)
+ struct config_file* cfg, struct comm_point* c, struct regional* region)
{
size_t rdata_len;
uint8_t* rdata_ptr;
if(sldns_buffer_remaining(pkt) < rdata_len)
return LDNS_RCODE_FORMERR;
rdata_ptr = sldns_buffer_current(pkt);
- if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
+ if(!parse_edns_options(rdata_ptr, rdata_len, edns, cfg, c, region))
return LDNS_RCODE_SERVFAIL;
/* ignore rrsigs */
struct rr_parse;
struct regional;
struct edns_option;
+struct config_file;
+struct comm_point;
/** number of buckets in parse rrset hash table. Must be power of 2. */
#define PARSE_TABLE_SIZE 32
* section. At end, right after EDNS data or no movement if failed.
* @param edns: the edns data allocated by the caller. Does not have to be
* initialised.
+ * @param cfg: the configuration (with nsid value etc.)
+ * @param c: commpoint to determine transport (if needed)
* @param region: region to alloc results in (edns option contents)
* @return: 0 on success, or an RCODE on error.
* RCODE formerr if OPT is badly formatted and so on.
*/
int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
- struct regional* region);
+ struct config_file* cfg, struct comm_point* c, struct regional* region);
/**
* Calculate hash value for rrset in packet.
return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen);
}
-static int edns_keepalive(struct edns_data* edns_out, struct edns_data* edns_in,
- struct comm_point* c, struct regional* region)
-{
- if(c->type == comm_udp)
- return 1;
-
- /* To respond with a Keepalive option, the client connection
- * must have received one message with a TCP Keepalive EDNS option,
- * and that option must have 0 length data. Subsequent messages
- * sent on that connection will have a TCP Keepalive option.
- */
- if(c->tcp_keepalive ||
- edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_KEEPALIVE)) {
- int keepalive = c->tcp_timeout_msec / 100;
- uint8_t data[2];
- data[0] = (uint8_t)((keepalive >> 8) & 0xff);
- data[1] = (uint8_t)(keepalive & 0xff);
- if(!edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_KEEPALIVE,
- sizeof(data), data, region))
- return 0;
- c->tcp_keepalive = 1;
- }
- return 1;
-}
-
-int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in,
- struct config_file* cfg, struct comm_point* c, struct regional* region)
-{
- if(cfg->do_tcp_keepalive &&
- !edns_keepalive(edns_out, edns_in, c, region))
- return 0;
-
- if (cfg->nsid && edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_NSID)
- && !edns_opt_list_append(&edns_out->opt_list_out,
- LDNS_EDNS_NSID, cfg->nsid_len, cfg->nsid, region))
- return 0;
-
- if(!cfg->pad_responses || c->type != comm_tcp || !c->ssl
- || !edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_PADDING)) {
- ; /* pass */
- }
-
- else if(!edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_PADDING
- , 0, NULL, region))
- return 0;
- else
- edns_out->padding_block_size = cfg->pad_responses_block_size;
-
- return 1;
-}
edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
socklen_t addrlen);
-/**
- * Apply common EDNS options.
- *
- * @param edns_out: initialised edns information with outbound edns.
- * @param edns_in: initialised edns information with received edns.
- * @param cfg: configuration.
- * @param c: comm channel.
- * @param region: the region to allocate the edns options in.
- */
-int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in,
- struct config_file* cfg, struct comm_point* c, struct regional* region);
-
#endif