IXFR special cases handling (2)
Fixes #307 (closed), see the issue description and the discussion below for details. I went for option A for case (2) as no other people voted. ;-). Case (3) has been modified as proposed by @jvcelak.
Merge request reports
Activity
680 674 } 681 675 682 676 if (adata->ext == NULL) { 683 if (!ixfr_enough_data(pkt)) { 706 696 if (adata->ext == NULL) { 707 697 NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0); 708 698 if (!zone_transfer_needed(adata->param->zone, pkt)) { 709 IXFRIN_LOG(LOG_WARNING, "master sent older serial, " 710 "ignoring"); 699 if (knot_pkt_section(pkt, KNOT_ANSWER)->count > 1) { The answer is probably malformed even if count == 0. And if the first RR is not a SOA, the zone_transfer_needed will return false as well. Which means that if you really want to check whether the answer is malformed, you should check it's content. Not only the count of records.
I don't know if this is worth logging, if there is so much extra work we have to do to evaluate if the answer is malformed.
137 139 self.check_record(section="answer", rtype=self.rtype, ttl=ttl, 138 140 rdata=rdata, nordata=nordata) 139 141 142 def check_xfr(self, rcode="NOERROR"): 143 '''Checks XFR message''' 144 145 self.resp, iter_copy = itertools.tee(self.resp) 146 147 # Get the first message. 148 for msg in iter_copy: 174 for rrset in msg.answer: 175 for rr in rrset: 176 if rr_count == 0: 177 if rr.rdtype != dns.rdatatype.SOA: 178 set_err("First RR is not SOA") 179 return 180 else: 181 soa_count += 1 182 183 elif rr_count == 1: 184 if rr.rdtype == dns.rdatatype.SOA: 185 set_err("Second RR is SOA") 186 return 187 else: 188 # OK, it has the format of AXFR 189 return 171 172 self.resp, iter_copy = itertools.tee(self.resp) 173 for msg in iter_copy: 174 for rrset in msg.answer: 175 for rr in rrset: 176 if rr_count == 0: 177 if rr.rdtype != dns.rdatatype.SOA: 178 set_err("First RR is not SOA") 179 return 180 else: 181 soa_count += 1 182 183 elif rr_count == 1: 184 if rr.rdtype == dns.rdatatype.SOA: 185 set_err("Second RR is SOA") 186 return 158 compare(dns.rcode.to_text(msg.rcode()), rc, "RCODE") 159 160 # Check the first message only. 161 break 162 163 # Checks whether the transfer is an AXFR-style IXFR 164 def check_axfr_style_ixfr(self, axfr=None): 165 # 1) QTYPE == IXFR && RCODE == NOERROR 166 self.check_xfr() 167 168 # 2) Check if Answer contains AXFR data (first SOA, second non-SOA) 169 soa_count = 0 170 rr_count = 0 171 172 self.resp, iter_copy = itertools.tee(self.resp) 173 for msg in iter_copy: 250 cnt = 0 251 if isinstance(self.resp, collections.Iterable): 252 self.resp, iter_copy = itertools.tee(self.resp) 253 for msg in iter_copy: 254 if not section or section == "answer": 255 sect = msg.answer 256 elif section == "additional": 257 sect = msg.additional 258 elif section == "authority": 259 sect = msg.authority 260 261 for rrset in sect: 262 if rrset.rdtype == rtype or rtype == dns.rdatatype.ANY: 263 cnt += len(rrset) 264 else: 265 if not section or section == "answer": Added 1 new commit:
- 6438a774 - ixfr: Format checking + removed redundant test
Added 1 new commit:
- e8f7952c - ixfr: Fixed format checking.
mentioned in commit 975c9464