@@ -139,12 +139,38 @@ static int stub_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
139139
140140DEFINE_HASH_OPS (stub_packet_hash_ops , DnsPacket , stub_packet_hash_func , stub_packet_compare_func );
141141
142+ static int reply_add_with_rrsig (
143+ DnsAnswer * * reply ,
144+ DnsResourceRecord * rr ,
145+ int ifindex ,
146+ DnsAnswerFlags flags ,
147+ DnsResourceRecord * rrsig ,
148+ bool with_rrsig ) {
149+ int r ;
150+
151+ assert (reply );
152+ assert (rr );
153+
154+ r = dns_answer_add_extend (reply , rr , ifindex , flags , rrsig );
155+ if (r < 0 )
156+ return r ;
157+
158+ if (with_rrsig && rrsig ) {
159+ r = dns_answer_add_extend (reply , rrsig , ifindex , flags , NULL );
160+ if (r < 0 )
161+ return r ;
162+ }
163+
164+ return 0 ;
165+ }
166+
142167static int dns_stub_collect_answer_by_question (
143168 DnsAnswer * * reply ,
144169 DnsAnswer * answer ,
145170 DnsQuestion * question ,
146171 bool with_rrsig ) { /* Add RRSIG RR matching each RR */
147172
173+ _cleanup_ (dns_resource_key_unrefp ) DnsResourceKey * redirected_key = NULL ;
148174 DnsAnswerItem * item ;
149175 int r ;
150176
@@ -153,36 +179,71 @@ static int dns_stub_collect_answer_by_question(
153179 /* Copies all RRs from 'answer' into 'reply', if they match 'question'. */
154180
155181 DNS_ANSWER_FOREACH_ITEM (item , answer ) {
156-
157182 if (question ) {
158- bool match = false;
159-
160183 r = dns_question_matches_rr (question , item -> rr , NULL );
161184 if (r < 0 )
162185 return r ;
163- else if (r > 0 )
164- match = true;
165- else {
166- r = dns_question_matches_cname_or_dname (question , item -> rr , NULL );
186+ if (r == 0 ) {
187+ _cleanup_free_ char * target = NULL ;
188+
189+ /* OK, so the RR doesn't directly match. Let's see if the RR is a matching
190+ * CNAME or DNAME */
191+
192+ r = dns_resource_record_get_cname_target (
193+ question -> keys [0 ],
194+ item -> rr ,
195+ & target );
196+ if (r == - EUNATCH )
197+ continue ; /* Not a CNAME/DNAME or doesn't match */
167198 if (r < 0 )
168199 return r ;
169- if (r > 0 )
170- match = true;
171- }
172200
173- if (!match )
174- continue ;
201+ dns_resource_key_unref (redirected_key );
202+
203+ /* There can only be one CNAME per name, hence no point in storing more than one here */
204+ redirected_key = dns_resource_key_new (question -> keys [0 ]-> class , question -> keys [0 ]-> type , target );
205+ if (!redirected_key )
206+ return - ENOMEM ;
207+ }
175208 }
176209
177- r = dns_answer_add_extend (reply , item -> rr , item -> ifindex , item -> flags , item -> rrsig );
210+ /* Mask the section info, we want the primary answers to always go without section info, so
211+ * that it is added to the answer section when we synthesize a reply. */
212+
213+ r = reply_add_with_rrsig (
214+ reply ,
215+ item -> rr ,
216+ item -> ifindex ,
217+ item -> flags & ~DNS_ANSWER_MASK_SECTIONS ,
218+ item -> rrsig ,
219+ with_rrsig );
178220 if (r < 0 )
179221 return r ;
222+ }
180223
181- if (with_rrsig && item -> rrsig ) {
182- r = dns_answer_add_extend (reply , item -> rrsig , item -> ifindex , item -> flags , NULL );
183- if (r < 0 )
184- return r ;
185- }
224+ if (!redirected_key )
225+ return 0 ;
226+
227+ /* This is a CNAME/DNAME answer. In this case also append where the redirections point to to the main
228+ * answer section */
229+
230+ DNS_ANSWER_FOREACH_ITEM (item , answer ) {
231+
232+ r = dns_resource_key_match_rr (redirected_key , item -> rr , NULL );
233+ if (r < 0 )
234+ return r ;
235+ if (r == 0 )
236+ continue ;
237+
238+ r = reply_add_with_rrsig (
239+ reply ,
240+ item -> rr ,
241+ item -> ifindex ,
242+ item -> flags & ~DNS_ANSWER_MASK_SECTIONS ,
243+ item -> rrsig ,
244+ with_rrsig );
245+ if (r < 0 )
246+ return r ;
186247 }
187248
188249 return 0 ;
@@ -197,7 +258,6 @@ static int dns_stub_collect_answer_by_section(
197258 bool with_dnssec ) { /* Include DNSSEC RRs. RRSIG, NSEC, … */
198259
199260 DnsAnswerItem * item ;
200- unsigned c = 0 ;
201261 int r ;
202262
203263 assert (reply );
@@ -218,22 +278,18 @@ static int dns_stub_collect_answer_by_section(
218278 if (((item -> flags ^ section ) & (DNS_ANSWER_SECTION_ANSWER |DNS_ANSWER_SECTION_AUTHORITY |DNS_ANSWER_SECTION_ADDITIONAL )) != 0 )
219279 continue ;
220280
221- r = dns_answer_add_extend (reply , item -> rr , item -> ifindex , item -> flags , item -> rrsig );
281+ r = reply_add_with_rrsig (
282+ reply ,
283+ item -> rr ,
284+ item -> ifindex ,
285+ item -> flags ,
286+ item -> rrsig ,
287+ with_dnssec );
222288 if (r < 0 )
223289 return r ;
224-
225- c ++ ;
226-
227- if (with_dnssec && item -> rrsig ) {
228- r = dns_answer_add_extend (reply , item -> rrsig , item -> ifindex , item -> flags , NULL );
229- if (r < 0 )
230- return r ;
231-
232- c ++ ;
233- }
234290 }
235291
236- return ( int ) c ;
292+ return 0 ;
237293}
238294
239295static int dns_stub_assign_sections (
0 commit comments