/** compress owner name of RR, return RETVAL_OUTMEM RETVAL_TRUNC */ static int compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt, struct regional* region, struct compress_tree_node** tree, size_t owner_pos, uint16_t* owner_ptr, int owner_labs) { struct compress_tree_node* p; struct compress_tree_node** insertpt = NULL; if(!*owner_ptr) { /* compress first time dname */ if((p = compress_tree_lookup(tree, key->rk.dname, owner_labs, &insertpt))) { if(p->labs == owner_labs) /* avoid ptr chains, since some software is * not capable of decoding ptr after a ptr. */ *owner_ptr = htons(PTR_CREATE(p->offset)); if(!write_compressed_dname(pkt, key->rk.dname, owner_labs, p)) return RETVAL_TRUNC; /* check if typeclass+4 ttl + rdatalen is available */ if(sldns_buffer_remaining(pkt) < 4+4+2) return RETVAL_TRUNC; } else { /* no compress */ if(sldns_buffer_remaining(pkt) < key->rk.dname_len+4+4+2) return RETVAL_TRUNC; sldns_buffer_write(pkt, key->rk.dname, key->rk.dname_len); if(owner_pos <= PTR_MAX_OFFSET) *owner_ptr = htons(PTR_CREATE(owner_pos)); } if(!compress_tree_store(key->rk.dname, owner_labs, owner_pos, region, p, insertpt)) return RETVAL_OUTMEM; } else { /* always compress 2nd-further RRs in RRset */ if(owner_labs == 1) { if(sldns_buffer_remaining(pkt) < 1+4+4+2) return RETVAL_TRUNC; sldns_buffer_write_u8(pkt, 0); } else { if(sldns_buffer_remaining(pkt) < 2+4+4+2) return RETVAL_TRUNC; sldns_buffer_write(pkt, owner_ptr, 2); } } return RETVAL_OK; }
/** compress any domain name to the packet, return RETVAL_* */ static int compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs, struct regional* region, struct compress_tree_node** tree) { struct compress_tree_node* p; struct compress_tree_node** insertpt = NULL; size_t pos = sldns_buffer_position(pkt); if((p = compress_tree_lookup(tree, dname, labs, &insertpt))) { if(!write_compressed_dname(pkt, dname, labs, p)) return RETVAL_TRUNC; } else { if(!dname_buffer_write(pkt, dname)) return RETVAL_TRUNC; } if(!compress_tree_store(dname, labs, pos, region, p, insertpt)) return RETVAL_OUTMEM; return RETVAL_OK; }
/** store query section in wireformat buffer, return RETVAL */ static int insert_query(struct query_info* qinfo, struct compress_tree_node** tree, ldns_buffer* buffer, struct regional* region) { if(ldns_buffer_remaining(buffer) < qinfo->qname_len+sizeof(uint16_t)*2) return RETVAL_TRUNC; /* buffer too small */ /* the query is the first name inserted into the tree */ if(!compress_tree_store(qinfo->qname, dname_count_labels(qinfo->qname), ldns_buffer_position(buffer), region, NULL, tree)) return RETVAL_OUTMEM; if(ldns_buffer_current(buffer) == qinfo->qname) ldns_buffer_skip(buffer, (ssize_t)qinfo->qname_len); else ldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len); ldns_buffer_write_u16(buffer, qinfo->qtype); ldns_buffer_write_u16(buffer, qinfo->qclass); return RETVAL_OK; }