/** compress a domain name */ static int write_compressed_dname(ldns_buffer* pkt, uint8_t* dname, int labs, struct compress_tree_node* p) { /* compress it */ int labcopy = labs - p->labs; uint8_t lablen; uint16_t ptr; if(labs == 1) { /* write root label */ if(ldns_buffer_remaining(pkt) < 1) return 0; ldns_buffer_write_u8(pkt, 0); return 1; } /* copy the first couple of labels */ while(labcopy--) { lablen = *dname++; if(ldns_buffer_remaining(pkt) < (size_t)lablen+1) return 0; ldns_buffer_write_u8(pkt, lablen); ldns_buffer_write(pkt, dname, lablen); dname += lablen; } /* insert compression ptr */ if(ldns_buffer_remaining(pkt) < 2) return 0; ptr = PTR_CREATE(p->offset); ldns_buffer_write_u16(pkt, ptr); return 1; }
/** * Fill CH class answer into buffer. Keeps query. * @param pkt: buffer * @param str: string to put into text record (<255). * @param edns: edns reply information. */ static void chaos_replystr(ldns_buffer* pkt, const char* str, struct edns_data* edns) { size_t len = strlen(str); unsigned int rd = LDNS_RD_WIRE(ldns_buffer_begin(pkt)); unsigned int cd = LDNS_CD_WIRE(ldns_buffer_begin(pkt)); if(len>255) len=255; /* cap size of TXT record */ ldns_buffer_clear(pkt); ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */ ldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA)); if(rd) LDNS_RD_SET(ldns_buffer_begin(pkt)); if(cd) LDNS_CD_SET(ldns_buffer_begin(pkt)); ldns_buffer_write_u16(pkt, 1); /* qdcount */ ldns_buffer_write_u16(pkt, 1); /* ancount */ ldns_buffer_write_u16(pkt, 0); /* nscount */ ldns_buffer_write_u16(pkt, 0); /* arcount */ (void)query_dname_len(pkt); /* skip qname */ ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qtype */ ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qclass */ ldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */ ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT); ldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH); ldns_buffer_write_u32(pkt, 0); /* TTL */ ldns_buffer_write_u16(pkt, sizeof(uint8_t) + len); ldns_buffer_write_u8(pkt, len); ldns_buffer_write(pkt, str, len); ldns_buffer_flip(pkt); edns->edns_version = EDNS_ADVERTISED_VERSION; edns->udp_size = EDNS_ADVERTISED_SIZE; edns->bits &= EDNS_DO; attach_edns_record(pkt, edns); }
int dname_buffer_write(ldns_buffer* pkt, uint8_t* dname) { uint8_t lablen; if(ldns_buffer_remaining(pkt) < 1) return 0; lablen = *dname++; ldns_buffer_write_u8(pkt, lablen); while(lablen) { if(ldns_buffer_remaining(pkt) < (size_t)lablen+1) return 0; ldns_buffer_write(pkt, dname, lablen); dname += lablen; lablen = *dname++; ldns_buffer_write_u8(pkt, lablen); } return 1; }
void attach_edns_record(ldns_buffer* pkt, struct edns_data* edns) { size_t len; if(!edns || !edns->edns_present) return; /* inc additional count */ ldns_buffer_write_u16_at(pkt, 10, ldns_buffer_read_u16_at(pkt, 10) + 1); len = ldns_buffer_limit(pkt); ldns_buffer_clear(pkt); ldns_buffer_set_position(pkt, len); /* write EDNS record */ ldns_buffer_write_u8(pkt, 0); /* '.' label */ ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_OPT); /* type */ ldns_buffer_write_u16(pkt, edns->udp_size); /* class */ ldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */ ldns_buffer_write_u8(pkt, edns->edns_version); ldns_buffer_write_u16(pkt, edns->bits); ldns_buffer_write_u16(pkt, 0); /* rdatalen */ ldns_buffer_flip(pkt); }
/* * Copies the packet header data to the buffer in wire format */ static ldns_status ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) { uint8_t flags; uint16_t arcount; if (ldns_buffer_reserve(buffer, 12)) { ldns_buffer_write_u16(buffer, ldns_pkt_id(packet)); flags = ldns_pkt_qr(packet) << 7 | ldns_pkt_get_opcode(packet) << 3 | ldns_pkt_aa(packet) << 2 | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet); ldns_buffer_write_u8(buffer, flags); flags = ldns_pkt_ra(packet) << 7 /*| ldns_pkt_z(packet) << 6*/ | ldns_pkt_ad(packet) << 5 | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet); ldns_buffer_write_u8(buffer, flags); ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet)); ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet)); ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet)); /* add EDNS0 and TSIG to additional if they are there */ arcount = ldns_pkt_arcount(packet); if (ldns_pkt_tsig(packet)) { arcount++; } if (ldns_pkt_edns(packet)) { arcount++; } ldns_buffer_write_u16(buffer, arcount); } return ldns_buffer_status(buffer); }
/** compress owner name of RR, return RETVAL_OUTMEM RETVAL_TRUNC */ static int compress_owner(struct ub_packed_rrset_key* key, ldns_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; 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(ldns_buffer_remaining(pkt) < 4+4+2) return RETVAL_TRUNC; } else { /* no compress */ if(ldns_buffer_remaining(pkt) < key->rk.dname_len+4+4+2) return RETVAL_TRUNC; ldns_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(ldns_buffer_remaining(pkt) < 1+4+4+2) return RETVAL_TRUNC; ldns_buffer_write_u8(pkt, 0); } else { if(ldns_buffer_remaining(pkt) < 2+4+4+2) return RETVAL_TRUNC; ldns_buffer_write(pkt, owner_ptr, 2); } } return RETVAL_OK; }
/** skip through file to { or ; */ static int skip_to_special(FILE* in, ldns_buffer* buf, int* line, int spec) { int rdlen; ldns_buffer_clear(buf); while((rdlen=readkeyword_bindfile(in, buf, line, 1))) { if(rdlen == 1 && isspace((int)*ldns_buffer_begin(buf))) { ldns_buffer_clear(buf); continue; } if(rdlen != 1 || *ldns_buffer_begin(buf) != (uint8_t)spec) { ldns_buffer_write_u8(buf, 0); log_err("trusted-keys, line %d, expected %c", *line, spec); return 0; } return 1; } log_err("trusted-keys, line %d, expected %c got EOF", *line, spec); return 0; }
ldns_status ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf) { size_t i; uint8_t *rdf_data; if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) { if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { rdf_data = ldns_rdf_data(rdf); for (i = 0; i < ldns_rdf_size(rdf); i++) { ldns_buffer_write_u8(buffer, LDNS_DNAME_NORMALIZE(rdf_data[i])); } } } else { /* direct copy for all other types */ if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf)); } } return ldns_buffer_status(buffer); }
/** * read contents of trusted-keys{ ... ; clauses and insert keys into storage. * @param anchors: where to store keys * @param buf: buffer to use * @param line: line number in file * @param in: file to read from. * @return 0 on error. */ static int process_bind_contents(struct val_anchors* anchors, ldns_buffer* buf, int* line, FILE* in) { /* loop over contents, collate strings before ; */ /* contents is (numbered): 0 1 2 3 4 5 6 7 8 */ /* name. 257 3 5 base64 base64 */ /* quoted value: 0 "111" 0 0 0 0 0 0 0 */ /* comments value: 1 "000" 1 1 1 "0 0 0 0" 1 */ int contnum = 0; int quoted = 0; int comments = 1; int rdlen; char* str = 0; ldns_buffer_clear(buf); while((rdlen=readkeyword_bindfile(in, buf, line, comments))) { if(rdlen == 1 && ldns_buffer_position(buf) == 1 && isspace((int)*ldns_buffer_begin(buf))) { /* starting whitespace is removed */ ldns_buffer_clear(buf); continue; } else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '"') { /* remove " from the string */ if(contnum == 0) { quoted = 1; comments = 0; } ldns_buffer_skip(buf, -1); if(contnum > 0 && quoted) { if(ldns_buffer_remaining(buf) < 8+1) { log_err("line %d, too long", *line); return 0; } ldns_buffer_write(buf, " DNSKEY ", 8); quoted = 0; comments = 1; } else if(contnum > 0) comments = !comments; continue; } else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == ';') { if(contnum < 5) { ldns_buffer_write_u8(buf, 0); log_err("line %d, bad key", *line); return 0; } ldns_buffer_skip(buf, -1); ldns_buffer_write_u8(buf, 0); str = strdup((char*)ldns_buffer_begin(buf)); if(!str) { log_err("line %d, allocation failure", *line); return 0; } if(!anchor_store_str(anchors, buf, str)) { log_err("line %d, bad key", *line); free(str); return 0; } free(str); ldns_buffer_clear(buf); contnum = 0; quoted = 0; comments = 1; continue; } else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '}') { if(contnum > 0) { ldns_buffer_write_u8(buf, 0); log_err("line %d, bad key before }", *line); return 0; } return 1; } else if(rdlen == 1 && isspace((int)ldns_buffer_current(buf)[-1])) { /* leave whitespace here */ } else { /* not space or whatnot, so actual content */ contnum ++; if(contnum == 1 && !quoted) { if(ldns_buffer_remaining(buf) < 8+1) { log_err("line %d, too long", *line); return 0; } ldns_buffer_write(buf, " DNSKEY ", 8); } } } log_err("line %d, EOF before }", *line); return 0; }
/** * Read a keyword skipping bind comments; spaces, specials, restkeywords. * The file is split into the following tokens: * * special characters, on their own, rdlen=1, { } doublequote ; * * whitespace becomes a single ' ' or tab. Newlines become spaces. * * other words ('keywords') * * comments are skipped if desired * / / C++ style comment to end of line * # to end of line * / * C style comment * / * @param in: file to read from. * @param buf: buffer, what is read is stored after current buffer position. * Space is left in the buffer to write a terminating 0. * @param line: line number is increased per line, for error reports. * @param comments: if 0, comments are not possible and become text. * if 1, comments are skipped entirely. * In BIND files, this is when reading quoted strings, for example * " base 64 text with / / in there " * @return the number of character written to the buffer. * 0 on end of file. */ static int readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line, int comments) { int c; int numdone = 0; while((c = getc(in)) != EOF ) { if(comments && c == '#') { /* # blabla */ skip_to_eol(in); (*line)++; continue; } else if(comments && c=='/' && numdone>0 && /* /_/ bla*/ ldns_buffer_read_u8_at(buf, ldns_buffer_position(buf)-1) == '/') { ldns_buffer_skip(buf, -1); numdone--; skip_to_eol(in); (*line)++; continue; } else if(comments && c=='*' && numdone>0 && /* /_* bla *_/ */ ldns_buffer_read_u8_at(buf, ldns_buffer_position(buf)-1) == '/') { ldns_buffer_skip(buf, -1); numdone--; /* skip to end of comment */ while(c != EOF && (c=getc(in)) != EOF ) { if(c == '*') { if((c=getc(in)) == '/') break; } if(c == '\n') (*line)++; } continue; } /* not a comment, complete the keyword */ if(numdone > 0) { /* check same type */ if(isspace(c)) { ungetc(c, in); return numdone; } if(is_bind_special(c)) { ungetc(c, in); return numdone; } } if(c == '\n') { c = ' '; (*line)++; } /* space for 1 char + 0 string terminator */ if(ldns_buffer_remaining(buf) < 2) { fatal_exit("trusted-keys, %d, string too long", *line); } ldns_buffer_write_u8(buf, (uint8_t)c); numdone++; if(isspace(c)) { /* collate whitespace into ' ' */ while((c = getc(in)) != EOF ) { if(c == '\n') (*line)++; if(!isspace(c)) { ungetc(c, in); break; } } return numdone; } if(is_bind_special(c)) return numdone; } return numdone; }
int output_cbor(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char *payload, size_t payloadlen) { ldns_pkt *pkt = 0; ldns_status ldns_rc; if (!payload) { return DUMP_CBOR_EINVAL; } if (!payloadlen) { return DUMP_CBOR_EINVAL; } /* if (!cbor_stringrefs) {*/ /* cbor_stringrefs = calloc(1, cbor_stringref_size);*/ /* }*/ if (!cbor_buf) { if (!(cbor_buf = calloc(1, cbor_size + cbor_reserve))) { return DUMP_CBOR_ENOMEM; } } if (cbor_flushed) { CborError cbor_err; cbor_encoder_init(&cbor_root, cbor_buf, cbor_size, 0); /* cbor_err = cbor_encode_tag(&cbor_root, 256);*/ /* if (cbor_err == CborNoError)*/ cbor_err = cbor_encoder_create_array(&cbor_root, &cbor_pkts, CborIndefiniteLength); if (cbor_err != CborNoError) { fprintf(stderr, "cbor init error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } cbor_flushed = 0; } ldns_rc = ldns_wire2pkt(&pkt, payload, payloadlen); if (ldns_rc != LDNS_STATUS_OK) { fprintf(stderr, "ldns error [%d]: %s\n", ldns_rc, ldns_get_errorstr_by_id(ldns_rc)); return DUMP_CBOR_ELDNS; } if (!pkt) { return DUMP_CBOR_ELDNS; } CborEncoder cbor, ip; CborError cbor_err = CborNoError; int should_flush = 0; cbor_err = append_cbor_map(&cbor_pkts, &cbor, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateSeconds", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_double(&cbor, (double)ts.tv_sec + ( (double)ts.tv_usec / 1000000 ), &should_flush); /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateNanoFractions", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ts.tv_usec * 1000, &should_flush);*/ if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ip", &should_flush); /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, proto, &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourceIpAddress", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(from), &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourcePort", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, sport, &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationIpAddress", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(to), &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationPort", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, dport, &should_flush);*/ if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &ip, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, proto, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(from), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, sport, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(to), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, dport, &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &ip, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ID", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_id(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QR", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_qr(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "Opcode", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_opcode(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AA", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_aa(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "TC", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_tc(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_rd(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RA", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ra(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ad(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "CD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_cd(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RCODE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_rcode(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QDCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_qdcount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ANCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_ancount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "NSCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_nscount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ARCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_arcount(pkt), &should_flush); /* questionRRs */ if (ldns_pkt_qdcount(pkt) > 0) { ldns_rr_list *list = ldns_pkt_question(pkt); ldns_rr *rr; size_t n, qdcount = ldns_pkt_qdcount(pkt); ldns_buffer *dname; char *dname_str; if (!list) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } rr = ldns_rr_list_rr(list, 0); if (!rr) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } if (!(dname = ldns_buffer_new(512))) { ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } ldns_buffer_write_u8(dname, 0); if (!(dname_str = ldns_buffer_export(dname))) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QNAME", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, dname_str, &should_flush); free(dname_str); ldns_buffer_free(dname); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QCLASS", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_class(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QTYPE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_type(rr), &should_flush); if (qdcount > 1) { CborEncoder queries; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "questionRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &queries, CborIndefiniteLength, &should_flush); for (n = 1; cbor_err == CborNoError && n < qdcount; n++) { CborEncoder query; rr = ldns_rr_list_rr(list, n); if (!rr) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } if (!(dname = ldns_buffer_new(512))) { ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } ldns_buffer_write_u8(dname, 0); if (!(dname_str = ldns_buffer_export(dname))) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (cbor_err == CborNoError) cbor_err = append_cbor_map(&queries, &query, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "NAME", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, dname_str, &should_flush); free(dname_str); ldns_buffer_free(dname); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "CLASS", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_class(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "TYPE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_type(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&queries, &query, &should_flush); } if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &queries, &should_flush); } } /* answerRRs */ if (ldns_pkt_ancount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "answerRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_answer(pkt), ldns_pkt_ancount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } /* authorityRRs */ if (ldns_pkt_nscount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "authorityRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_authority(pkt), ldns_pkt_nscount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } /* additionalRRs */ if (ldns_pkt_arcount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "additionalRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_additional(pkt), ldns_pkt_arcount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } ldns_pkt_free(pkt); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor_pkts, &cbor, &should_flush); if (cbor_err != CborNoError) { fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } if (should_flush) { if ((cbor_err = cbor_encoder_close_container_checked(&cbor_root, &cbor_pkts)) != CborNoError) { fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } fprintf(stderr, "cbor output: %lu bytes\n", cbor_encoder_get_buffer_size(&cbor_root, cbor_buf)); cbor_flushed = 1; return DUMP_CBOR_FLUSH; } return DUMP_CBOR_OK; }
static CborError cbor_ldns_rr_list(CborEncoder *encoder, ldns_rr_list *list, size_t count, int *should_flush) { CborError cbor_err = CborNoError; size_t n; ldns_buffer *dname; char *dname_str; if (!encoder) { return CborErrorInternalError; } if (!list) { return CborErrorInternalError; } if (!count) { return CborErrorInternalError; } if (!should_flush) { return CborErrorInternalError; } for (n = 0; cbor_err == CborNoError && n < count; n++) { CborEncoder cbor_rr; uint8_t *rdata_bytes; ldns_buffer *rdata; ldns_rr *rr = ldns_rr_list_rr(list, n); size_t rd_count; if (!rr) { return CborErrorInternalError; } rd_count = ldns_rr_rd_count(rr); if (!(dname = ldns_buffer_new(512))) { return CborErrorOutOfMemory; } if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) { ldns_buffer_free(dname); return CborErrorInternalError; } ldns_buffer_write_u8(dname, 0); if (!(dname_str = ldns_buffer_export(dname))) { ldns_buffer_free(dname); return CborErrorOutOfMemory; } if (cbor_err == CborNoError) cbor_err = append_cbor_map(encoder, &cbor_rr, CborIndefiniteLength, should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "NAME", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, dname_str, should_flush); free(dname_str); ldns_buffer_free(dname); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "CLASS", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_class(rr), should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "TYPE", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_type(rr), should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "TTL", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_ttl(rr), should_flush); if (rd_count == 1) { if (!(rdata = ldns_buffer_new(64*1024))) { return CborErrorOutOfMemory; } if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, 0)) != LDNS_STATUS_OK) { ldns_buffer_free(rdata); return CborErrorInternalError; } if (!(rdata_bytes = ldns_buffer_export(rdata))) { ldns_buffer_free(rdata); return CborErrorOutOfMemory; } if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "RDLENGTH", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_buffer_position(rdata), should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "RDATA", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_bytes(&cbor_rr, rdata_bytes, ldns_buffer_position(rdata), should_flush); free(rdata_bytes); ldns_buffer_free(rdata); } else if (rd_count > 1) { size_t n2; CborEncoder rr_set; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "rrSet", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor_rr, &rr_set, CborIndefiniteLength, should_flush); for (n2 = 0; n2 < rd_count; n2++) { if (!(rdata = ldns_buffer_new(64*1024))) { return CborErrorOutOfMemory; } if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, n2)) != LDNS_STATUS_OK) { ldns_buffer_free(rdata); return CborErrorInternalError; } if (!(rdata_bytes = ldns_buffer_export(rdata))) { ldns_buffer_free(rdata); return CborErrorOutOfMemory; } if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&rr_set, "RDLENGTH", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&rr_set, ldns_buffer_position(rdata), should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&rr_set, "RDATA", should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_bytes(&rr_set, rdata_bytes, ldns_buffer_position(rdata), should_flush); free(rdata_bytes); ldns_buffer_free(rdata); } if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor_rr, &rr_set, should_flush); } if (cbor_err == CborNoError) cbor_err = close_cbor_container(encoder, &cbor_rr, should_flush); } return cbor_err; }