Parcourir la source

[1389] fixed another small bug: take into account the length of the question
section. also extended tests to check the length the actual wire format
data for some specific cases.

JINMEI Tatuya il y a 13 ans
Parent
commit
5468c7defd
2 fichiers modifiés avec 37 ajouts et 5 suppressions
  1. 29 3
      src/bin/xfrout/tests/xfrout_test.py.in
  2. 8 2
      src/bin/xfrout/xfrout.py.in

+ 29 - 3
src/bin/xfrout/tests/xfrout_test.py.in

@@ -67,10 +67,12 @@ class MySocket():
         self.sendqueue = self.sendqueue[size:]
         return result
 
-    def read_msg(self, parse_options=Message.PARSE_DEFAULT):
+    def read_msg(self, parse_options=Message.PARSE_DEFAULT, need_len=False):
         sent_data = self.readsent()
         get_msg = Message(Message.PARSE)
         get_msg.from_wire(bytes(sent_data[2:]), parse_options)
+        if need_len:
+            return (get_msg, len(sent_data) - 2)
         return get_msg
 
     def clear_send(self):
@@ -879,7 +881,9 @@ class TestXfroutSession(TestXfroutSessionBase):
         self.assertTrue(rrsets_equal(self.soa_rrset,
                                      r.get_section(Message.SECTION_ANSWER)[0]))
         # The second message should contain the beginning SOA, and only that RR
-        r = self.sock.read_msg()
+        # The wire format data should have the possible maximum size.
+        r, rlen = self.sock.read_msg(need_len=True)
+        self.assertEqual(65535, rlen)
         self.assertEqual(1, r.get_rr_count(Message.SECTION_ANSWER))
         self.assertTrue(rrsets_equal(test_rr,
                                      r.get_section(Message.SECTION_ANSWER)[0]))
@@ -889,8 +893,30 @@ class TestXfroutSession(TestXfroutSessionBase):
         self.assertTrue(rrsets_equal(self.soa_rrset,
                                      r.get_section(Message.SECTION_ANSWER)[0]))
 
+    def test_reply_xfrout_query_axfr_maxlen_with_soa(self):
+        # Similar to the 'maxlen' test, but the first message should be
+        # able to contain both SOA and the large RR.
+        # For this test we use '.' for all owner names and names in RDATA
+        # to avoid having unexpected results due to compression.
+        soa = RRset(Name('.'), RRClass.IN(), RRType.SOA(), RRTTL(3600))
+        soa.add_rdata(Rdata(RRType.SOA(), RRClass.IN(), '. . 0 0 0 0 0'))
+        self.mdata = self.create_request_data(zone_name=Name('.'))
+        self.xfrsess._soa = soa
+        # The first message will contain the question (5 bytes), so the
+        # test RDATA should allow a room for that.
+        test_rr = create_generic(Name('.'), 65512 - 5 - get_rrset_len(soa))
+        self.xfrsess._iterator = [soa, test_rr]
+        self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
+        r, rlen = self.sock.read_msg(need_len=True)
+        self.assertEqual(65535, rlen)
+        self.assertEqual(2, r.get_rr_count(Message.SECTION_ANSWER))
+        self.assertTrue(rrsets_equal(soa,
+                                     r.get_section(Message.SECTION_ANSWER)[0]))
+        self.assertTrue(rrsets_equal(test_rr,
+                                     r.get_section(Message.SECTION_ANSWER)[1]))
+
     def test_reply_xfrout_query_axfr_toobigdata(self):
-        # Similar to the previous test, but the RR doesn't even fit in a
+        # Similar to the 'maxlen' test, but the RR doesn't even fit in a
         # single message.
         self.xfrsess._soa = self.soa_rrset
         test_rr = create_generic(Name('.'), 65513) # 1 byte larger than 'max'

+ 8 - 2
src/bin/xfrout/xfrout.py.in

@@ -556,7 +556,13 @@ class XfroutSession():
         #TODO, there should be a better way to insert rrset.
         msg.make_response()
         msg.set_header_flag(Message.HEADERFLAG_AA)
-        message_upper_len = XFROUT_DNS_HEADER_SIZE
+        # Reserved space for the fixed header size, the size of the question
+        # section, and TSIG size (when included).  The size of the question
+        # section is the sum of the qname length and the size of the
+        # fixed-length fields (type and class, 2 bytes each).
+        message_upper_len = XFROUT_DNS_HEADER_SIZE + \
+            msg.get_question()[0].get_name().get_length() + 4 + \
+            self._tsig_len
 
         # If the iterator is None, we are responding to IXFR with a single
         # SOA RR.
@@ -567,7 +573,7 @@ class XfroutSession():
 
         # Add the beginning SOA
         msg.add_rrset(Message.SECTION_ANSWER, self._soa)
-        message_upper_len = get_rrset_len(self._soa) + self._tsig_len
+        message_upper_len += get_rrset_len(self._soa)
 
         # Add the rest of the zone/diff contets
         for rrset in self._iterator: