1/* 2 * answer.c -- manipulating query answers and encoding them. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10#include "config.h" 11 12#include <string.h> 13 14#include "answer.h" 15#include "packet.h" 16#include "query.h" 17 18void 19answer_init(answer_type *answer) 20{ 21 answer->rrset_count = 0; 22} 23 24int 25answer_add_rrset(answer_type *answer, rr_section_type section, 26 domain_type *domain, rrset_type *rrset) 27{ 28 size_t i; 29 30 assert(section >= ANSWER_SECTION && section < RR_SECTION_COUNT); 31 assert(domain); 32 assert(rrset); 33 34 /* Don't add an RRset multiple times. */ 35 for (i = 0; i < answer->rrset_count; ++i) { 36 if (answer->rrsets[i] == rrset && 37 answer->domains[i]->number == domain->number) { 38 if (section < answer->section[i]) { 39 answer->section[i] = section; 40 return 1; 41 } else { 42 return 0; 43 } 44 } 45 } 46 47 if (answer->rrset_count >= MAXRRSPP) { 48 /* XXX: Generate warning/error? */ 49 return 0; 50 } 51 52 answer->section[answer->rrset_count] = section; 53 answer->domains[answer->rrset_count] = domain; 54 answer->rrsets[answer->rrset_count] = rrset; 55 ++answer->rrset_count; 56 57 return 1; 58} 59 60void 61encode_answer(query_type *q, const answer_type *answer) 62{ 63 uint16_t counts[RR_SECTION_COUNT]; 64 rr_section_type section; 65 size_t i; 66 int minimal_respsize = IPV4_MINIMAL_RESPONSE_SIZE; 67 int done = 0; 68 69#if defined(INET6) && defined(MINIMAL_RESPONSES) 70 if (q->client_addr.ss_family == AF_INET6) 71 minimal_respsize = IPV6_MINIMAL_RESPONSE_SIZE; 72#endif 73 74 for (section = ANSWER_SECTION; section < RR_SECTION_COUNT; ++section) { 75 counts[section] = 0; 76 } 77 78 for (section = ANSWER_SECTION; 79 !TC(q->packet) && section < RR_SECTION_COUNT; 80 ++section) { 81 82 for (i = 0; !TC(q->packet) && i < answer->rrset_count; ++i) { 83 if (answer->section[i] == section) { 84 counts[section] += packet_encode_rrset( 85 q, 86 answer->domains[i], 87 answer->rrsets[i], 88 section, minimal_respsize, &done); 89 } 90 } 91#ifdef MINIMAL_RESPONSES 92 /** 93 * done is set prematurely, because the minimal response size 94 * has been reached. No need to try adding RRsets in following 95 * sections. 96 */ 97 if (done) { 98 /* delegations should have a usable address in it */ 99 if(section == ADDITIONAL_A_SECTION && 100 counts[ADDITIONAL_A_SECTION] == 0 && 101 q->delegation_domain) 102 TC_SET(q->packet); 103 break; 104 } 105#endif 106 } 107 108 ANCOUNT_SET(q->packet, counts[ANSWER_SECTION]); 109 NSCOUNT_SET(q->packet, 110 counts[AUTHORITY_SECTION] 111 + counts[OPTIONAL_AUTHORITY_SECTION]); 112 ARCOUNT_SET(q->packet, 113 counts[ADDITIONAL_A_SECTION] 114 + counts[ADDITIONAL_AAAA_SECTION] 115 + counts[ADDITIONAL_OTHER_SECTION]); 116} 117