/** read qinfo from next three words */ static char* load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf, struct regional* region) { /* s is part of the buf */ char* s = str; ldns_rr* rr; ldns_status status; /* skip three words */ s = strchr(str, ' '); if(s) s = strchr(s+1, ' '); if(s) s = strchr(s+1, ' '); if(!s) { log_warn("error line too short, %s", str); return NULL; } s[0] = 0; s++; /* parse them */ status = ldns_rr_new_question_frm_str(&rr, str, NULL, NULL); if(status != LDNS_STATUS_OK) { log_warn("error cannot parse: %s %s", ldns_get_errorstr_by_id(status), str); return NULL; } qinfo->qtype = ldns_rr_get_type(rr); qinfo->qclass = ldns_rr_get_class(rr); ldns_buffer_clear(buf); status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr)); ldns_rr_free(rr); if(status != LDNS_STATUS_OK) { log_warn("error cannot dname2wire: %s", ldns_get_errorstr_by_id(status)); return NULL; } ldns_buffer_flip(buf); qinfo->qname_len = ldns_buffer_limit(buf); qinfo->qname = (uint8_t*)regional_alloc_init(region, ldns_buffer_begin(buf), ldns_buffer_limit(buf)); if(!qinfo->qname) { log_warn("error out of memory"); return NULL; } return s; }
/* Reads one entry from file. Returns entry or NULL on error. */ struct entry* read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, ldns_rdf** origin, ldns_rdf** prev_rr) { struct entry* current = NULL; char line[MAX_LINE]; char* parse; ldns_pkt_section add_section = LDNS_SECTION_QUESTION; struct reply_packet *cur_reply = NULL; bool reading_hex = false; ldns_buffer* hex_data_buffer = NULL; while(fgets(line, (int)sizeof(line), in) != NULL) { line[MAX_LINE-1] = 0; parse = line; (*lineno) ++; while(isspace((int)*parse)) parse++; /* test for keywords */ if(isendline(*parse)) continue; /* skip comment and empty lines */ if(str_keyword(&parse, "ENTRY_BEGIN")) { if(current) { error("%s line %d: previous entry does not ENTRY_END", name, *lineno); } current = new_entry(); current->lineno = *lineno; cur_reply = entry_add_reply(current); continue; } else if(str_keyword(&parse, "$ORIGIN")) { get_origin(name, *lineno, origin, parse); continue; } else if(str_keyword(&parse, "$TTL")) { *default_ttl = (uint32_t)atoi(parse); continue; } /* working inside an entry */ if(!current) { error("%s line %d: expected ENTRY_BEGIN but got %s", name, *lineno, line); } if(str_keyword(&parse, "MATCH")) { matchline(parse, current); } else if(str_keyword(&parse, "REPLY")) { replyline(parse, cur_reply->reply); } else if(str_keyword(&parse, "ADJUST")) { adjustline(parse, current, cur_reply); } else if(str_keyword(&parse, "EXTRA_PACKET")) { cur_reply = entry_add_reply(current); } else if(str_keyword(&parse, "SECTION")) { if(str_keyword(&parse, "QUESTION")) add_section = LDNS_SECTION_QUESTION; else if(str_keyword(&parse, "ANSWER")) add_section = LDNS_SECTION_ANSWER; else if(str_keyword(&parse, "AUTHORITY")) add_section = LDNS_SECTION_AUTHORITY; else if(str_keyword(&parse, "ADDITIONAL")) add_section = LDNS_SECTION_ADDITIONAL; else error("%s line %d: bad section %s", name, *lineno, parse); } else if(str_keyword(&parse, "HEX_ANSWER_BEGIN")) { hex_data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); reading_hex = true; } else if(str_keyword(&parse, "HEX_ANSWER_END")) { if (!reading_hex) { error("%s line %d: HEX_ANSWER_END read but no HEX_ANSWER_BEGIN keyword seen", name, *lineno); } reading_hex = false; cur_reply->reply_from_hex = data_buffer2wire(hex_data_buffer); ldns_buffer_free(hex_data_buffer); } else if(str_keyword(&parse, "ENTRY_END")) { return current; } else if(reading_hex) { ldns_buffer_printf(hex_data_buffer, line); } else { /* it must be a RR, parse and add to packet. */ ldns_rr* n = NULL; ldns_status status; if(add_section == LDNS_SECTION_QUESTION) status = ldns_rr_new_question_frm_str( &n, parse, *origin, prev_rr); else status = ldns_rr_new_frm_str(&n, parse, *default_ttl, *origin, prev_rr); if(status != LDNS_STATUS_OK) error("%s line %d:\n\t%s: %s", name, *lineno, ldns_get_errorstr_by_id(status), parse); ldns_pkt_push_rr(cur_reply->reply, add_section, n); } } if (reading_hex) { error("%s: End of file reached while still reading hex, " "missing HEX_ANSWER_END\n", name); } if(current) { error("%s: End of file reached while reading entry. " "missing ENTRY_END\n", name); } return 0; }