Browse 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 13 years ago
parent
commit
5468c7defd
2 changed files with 37 additions and 5 deletions
  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: