uint8_t* context_serialize_answer(struct ctx_query* q, int err, ldns_buffer* pkt, uint32_t* len) { /* answer format * o uint32 cmd * o uint32 id * o uint32 error_code * o uint32 msg_security * o uint32 length of why_bogus string (+1 for eos); 0 absent. * o why_bogus_string * o the remainder is the answer msg from resolver lookup. * remainder can be length 0. */ size_t pkt_len = pkt?ldns_buffer_remaining(pkt):0; size_t wlen = (pkt&&q->res->why_bogus)?strlen(q->res->why_bogus)+1:0; uint8_t* p; *len = sizeof(uint32_t)*5 + pkt_len + wlen; p = (uint8_t*)malloc(*len); if(!p) return NULL; ldns_write_uint32(p, UB_LIBCMD_ANSWER); ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err); ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security); ldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)wlen); if(wlen > 0) memmove(p+5*sizeof(uint32_t), q->res->why_bogus, wlen); if(pkt_len > 0) memmove(p+5*sizeof(uint32_t)+wlen, ldns_buffer_begin(pkt), pkt_len); return p; }
uint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len) { /* format of cancel: * o uint32 cmd * o uint32 async-id */ uint8_t* p = (uint8_t*)malloc(2*sizeof(uint32_t)); if(!p) return NULL; *len = 2*sizeof(uint32_t); ldns_write_uint32(p, UB_LIBCMD_CANCEL); ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); return p; }
uint8_t* context_serialize_quit(uint32_t* len) { uint8_t* p = (uint8_t*)malloc(sizeof(uint32_t)); if(!p) return NULL; *len = sizeof(uint32_t); ldns_write_uint32(p, UB_LIBCMD_QUIT); return p; }
/** synthesize a CNAME rrset */ static struct rrset_parse* synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias, size_t aliaslen, struct regional* region, struct msg_parse* msg, struct rrset_parse* rrset, struct rrset_parse* prev, struct rrset_parse* nx, ldns_buffer* pkt) { struct rrset_parse* cn = (struct rrset_parse*)regional_alloc(region, sizeof(struct rrset_parse)); if(!cn) return NULL; memset(cn, 0, sizeof(*cn)); cn->rr_first = (struct rr_parse*)regional_alloc(region, sizeof(struct rr_parse)); if(!cn->rr_first) return NULL; cn->rr_last = cn->rr_first; /* CNAME from sname to alias */ cn->dname = (uint8_t*)regional_alloc(region, *snamelen); if(!cn->dname) return NULL; dname_pkt_copy(pkt, cn->dname, *sname); cn->dname_len = *snamelen; cn->type = LDNS_RR_TYPE_CNAME; cn->section = rrset->section; cn->rrset_class = rrset->rrset_class; cn->rr_count = 1; cn->size = sizeof(uint16_t) + aliaslen; cn->hash=pkt_hash_rrset(pkt, cn->dname, cn->type, cn->rrset_class, 0); /* allocate TTL + rdatalen + uncompressed dname */ memset(cn->rr_first, 0, sizeof(struct rr_parse)); cn->rr_first->outside_packet = 1; cn->rr_first->ttl_data = (uint8_t*)regional_alloc(region, sizeof(uint32_t)+sizeof(uint16_t)+aliaslen); if(!cn->rr_first->ttl_data) return NULL; ldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */ ldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen); memmove(cn->rr_first->ttl_data+6, alias, aliaslen); cn->rr_first->size = sizeof(uint16_t)+aliaslen; /* link it in */ cn->rrset_all_next = nx; if(prev) prev->rrset_all_next = cn; else msg->rrset_first = cn; if(nx == NULL) msg->rrset_last = cn; msg->rrset_count ++; msg->an_rrsets++; /* it is not inserted in the msg hashtable. */ *sname = cn->rr_first->ttl_data + sizeof(uint32_t)+sizeof(uint16_t); *snamelen = aliaslen; return cn; }
uint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len) { /* format for new query is * o uint32 cmd * o uint32 id * o uint32 type * o uint32 class * o rest queryname (string) */ uint8_t* p; size_t slen = strlen(q->res->qname) + 1/*end of string*/; *len = sizeof(uint32_t)*4 + slen; p = (uint8_t*)malloc(*len); if(!p) return NULL; ldns_write_uint32(p, UB_LIBCMD_NEWQUERY); ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)q->res->qtype); ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->res->qclass); memmove(p+4*sizeof(uint32_t), q->res->qname, slen); return p; }