Browse Source

[1389] fixed another off-by-one bug in _send_message_with_last_soa().

JINMEI Tatuya 13 years ago
parent
commit
560122414a
2 changed files with 28 additions and 4 deletions
  1. 19 0
      src/bin/xfrout/tests/xfrout_test.py.in
  2. 9 4
      src/bin/xfrout/xfrout.py.in

+ 19 - 0
src/bin/xfrout/tests/xfrout_test.py.in

@@ -915,6 +915,25 @@ class TestXfroutSession(TestXfroutSessionBase):
         self.assertTrue(rrsets_equal(test_rr,
                                      r.get_section(Message.SECTION_ANSWER)[1]))
 
+    def test_reply_xfrout_query_axfr_maxlen_with_soa2(self):
+        # Similar to the previous test, but the first message cannot contain
+        # both SOA and the long RR due to the question section.  The second
+        # message should be able to contain both.
+        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
+        test_rr = create_generic(Name('.'), 65512 - get_rrset_len(soa))
+        self.xfrsess._iterator = [soa, test_rr]
+        self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
+        r = self.sock.read_msg()
+        self.assertEqual(1, r.get_rr_count(Message.SECTION_ANSWER))
+        self.assertTrue(rrsets_equal(soa,
+                                     r.get_section(Message.SECTION_ANSWER)[0]))
+        r, rlen = self.sock.read_msg(need_len=True)
+        self.assertEqual(65535, rlen)
+        self.assertEqual(2, r.get_rr_count(Message.SECTION_ANSWER))
+
     def test_reply_xfrout_query_axfr_toobigdata(self):
         # Similar to the 'maxlen' test, but the RR doesn't even fit in a
         # single message.

+ 9 - 4
src/bin/xfrout/xfrout.py.in

@@ -540,15 +540,20 @@ class XfroutSession():
 
     def _send_message_with_last_soa(self, msg, sock_fd, rrset_soa,
                                     message_upper_len):
-        '''Add the SOA record to the end of message. If it can't be
-        added, a new message should be created to send out the last soa .
+        '''Add the SOA record to the end of message.
+
+        If it would exceed the maximum allowable size of a message, a new
+        message will be created to send out the last SOA.
+
+        We assume a message with a single SOA can always fit the buffer
+        with or without TSIG.  In theory this could be wrong if TSIG is
+        stupidly large, but in practice this assumption should be reasonable.
         '''
-        if (message_upper_len + self._tsig_len + get_rrset_len(rrset_soa) >=
+        if (message_upper_len + self._tsig_len + get_rrset_len(rrset_soa) >
             XFROUT_MAX_MESSAGE_SIZE):
             self._send_message(sock_fd, msg, self._tsig_ctx)
             msg = self._clear_message(msg)
 
-        # If tsig context exist, sign the last packet
         msg.add_rrset(Message.SECTION_ANSWER, rrset_soa)
         self._send_message(sock_fd, msg, self._tsig_ctx)