[svn] commit: r2628 - in /branches/trac289/src/bin/xfrin: xfrin.py.in xfrin.spec.pre.in

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Aug 4 10:49:38 UTC 2010


Author: zhanglikun
Date: Wed Aug  4 10:49:38 2010
New Revision: 2628

Log:
Refactor the code of xfrin and add config item 'masters' to xfrin, make sure when xfrin get the notify command from zone manager, the zone transfer will be triggered.

Modified:
    branches/trac289/src/bin/xfrin/xfrin.py.in
    branches/trac289/src/bin/xfrin/xfrin.spec.pre.in

Modified: branches/trac289/src/bin/xfrin/xfrin.py.in
==============================================================================
--- branches/trac289/src/bin/xfrin/xfrin.py.in (original)
+++ branches/trac289/src/bin/xfrin/xfrin.py.in Wed Aug  4 10:49:38 2010
@@ -362,18 +362,19 @@
 
 class Xfrin:
     def __init__(self, verbose = False):
+        self._max_transfers_in = 10
+        #TODO, this is the temp way to set the zone's master.
+        self._masters = {} 
         self._cc_setup()
-        self._max_transfers_in = 10
         self.recorder = XfrinRecorder()
         self._shutdown_event = threading.Event()
         self._verbose = verbose
 
     def _cc_setup(self):
-        '''
-This method is used only as part of initialization, but is implemented
-separately for convenience of unit tests; by letting the test code override
-this method we can test most of this class without requiring a command channel.
-'''
+        '''This method is used only as part of initialization, but is 
+        implemented separately for convenience of unit tests; by letting 
+        the test code override this method we can test most of this class 
+        without requiring a command channel.'''
         # Create one session for sending command to other modules, because the 
         # listening session will block the send operation.
         self._send_cc_session = isc.cc.Session()
@@ -381,16 +382,32 @@
                                               self.config_handler,
                                               self.command_handler)
         self._module_cc.start()
+        config_data = self._module_cc.get_full_config()
+        self._max_transfers_in = config_data.get("transfers_in")
+        self._masters = config_data.get('masters')
 
     def _cc_check_command(self):
-        '''
-This is a straightforward wrapper for cc.check_command, but provided as
-a separate method for the convenience of unit tests.
-'''
+        '''This is a straightforward wrapper for cc.check_command, 
+        but provided as a separate method for the convenience 
+        of unit tests.'''
         self._module_cc.check_command()
 
     def config_handler(self, new_config):
-        # TODO, process new config data
+        self._max_transfers_in = new_config.get("transfers_in") or self._max_transfers_in
+        new_master = new_config.get('masters')
+        if new_master:
+            # Check if the new master is valid, there should be library for check it.
+            # and user should change the port and address together.
+            try:
+                new_master['address'] = new_master.get('address') or self._masters.get('address')
+                new_master['port'] = new_master.get('port') or self._masters.get('port')
+                check_addr_port(new_master.get('address'), new_master.get('port'))
+                self._masters = new_master
+            except:
+                errmsg = "bad format for zone's master: " + str(new_master)
+                log_error(errmsg)
+                return create_answer(1, errmsg)
+
         return create_answer(0)
 
     def shutdown(self):
@@ -404,66 +421,31 @@
                 continue
             th.join()
 
-
     def command_handler(self, command, args):
         answer = create_answer(0)
         try:
             if command == 'shutdown':
                 self._shutdown_event.set()
-            elif command == 'retransfer' or command == 'refresh':
-                (zone_name, rrclass,
-                 master_addr, db_file) = self._parse_cmd_params(args)
-                ret = self.xfrin_start(zone_name, rrclass, db_file,
-                                       master_addr,
-                                   False if command == 'retransfer' else True)
-                answer = create_answer(ret[0], ret[1])
-            elif command == 'notify':
-                # This is the temporary implementation for notify.
-                # actually the notfiy command should be sent to the
-                # Zone Manager module.  Being temporary, we separate this case
-                # from refresh/retransfer while we could (and should otherwise)
-                # share the code.
-                (zone_name, rrclass,
-                 master_addr, db_file) = self._parse_cmd_params(args)
-
-                # XXX: master_addr is the sender of the notify message.
-                # It's very dangerous to naively trust it as the source of
-                # subsequent zone transfer; any remote node can easily exploit
-                # it to mount zone poisoning or DoS attacks.  We should
-                # locally identify the appropriate set of master servers.
-                # For now, we disable the code below.
-                master_is_valid = False 
-
-                if master_is_valid:
-                    ret = self.xfrin_start(zone_name, rrclass, db_file,
-                                           master_addr, True)
-                else:
-                    errmsg = 'Failed to validate the master address ('
-                    errmsg += args['master'] + '), ignoring notify'
-                    ret = [1, errmsg]
+            elif command == 'notify' or \
+                 command == 'retransfer' or \
+                 command == 'refresh':
+                # Xfrin maybe receives the refresh/notify command from zone manager, or 
+                # the retransfer/refresh from cmdctl(sent by bindctl).
+                # If the command has specified master address, do transfer from the 
+                # master address, or else do transfer from the configured masters.                
+                # notify command maybe has the parameters which 
+                # specify the notifyfrom address and port, according the RFC1996, zone
+                # transfer should starts first from the notifyfrom, but now, let 'TODO' it.
+                (zone_name, rrclass, master_addr, db_file) = self._parse_cmd_params(args)
+                ret = self.xfrin_start(zone_name, rrclass, 
+                                       db_file, master_addr,
+                                       (False if command == 'retransfer' else True))
                 answer = create_answer(ret[0], ret[1])
             else:
                 answer = create_answer(1, 'unknown command: ' + command)
-
         except XfrinException as err:
             answer = create_answer(1, str(err))
-
         return answer
-
-    def publish_xfrin_news(self, zone_name, xfr_result):
-        '''Send command to xfrout/zone manager module.
-        If xfrin has finished successfully for one zone, tell the good 
-        news(command: zone_new_data_ready) to zone manager and xfrout.
-        if xfrin failed, just tell the bad news to zone manager, so that 
-        it can reset the refresh timer for that zone. '''
-        param = {'zone_name': zone_name}
-        if xfr_result == XFRIN_OK:
-            msg = create_command(notify_out.ZONE_NEW_DATA_READY_CMD, param)
-            self._send_cc_session.group_sendmsg(msg, XFROUT_MODULE_NAME)
-            self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
-        else:
-            msg = create_command(ZONE_XFRIN_FAILED, param)
-            self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
 
     def _parse_cmd_params(self, args):
         zone_name = args.get('zone_name')
@@ -472,9 +454,6 @@
 
         rrclass = args.get('zone_class')
         if not rrclass:
-            # The default RR class is IN.  We should fix this so that
-            # the class is always passed in the command arg (where we specify
-            # the default)
             rrclass = RRClass.IN()
         else:
             try:
@@ -482,15 +461,19 @@
             except InvalidRRClass as e:
                 raise XfrinException('invalid RRClass: ' + rrclass)
 
-        master = args.get('master')
-        if not master:
-            raise XfrinException('master address should be provided')
-
         port_str = args.get('port')
         if not port_str:
             port_str = DEFAULT_MASTER_PORT
+
+        master = args.get('master')
+        if not master:
+            if len(self._masters) > 0:
+                master = self._masters.get('address')
+                port_str = self._masters.get('port')
+            else:
+                raise XfrinException("zone's master should be provided")
+
         master_addrinfo = check_addr_port(master, port_str)
-
         db_file = args.get('db_file')
         if not db_file:
             #TODO, the db file path should be got in auth server's configuration
@@ -509,6 +492,21 @@
 
         return (zone_name, rrclass, master_addrinfo, db_file)
 
+    def publish_xfrin_news(self, zone_name, xfr_result):
+        '''Send command to xfrout/zone manager module.
+        If xfrin has finished successfully for one zone, tell the good 
+        news(command: zone_new_data_ready) to zone manager and xfrout.
+        if xfrin failed, just tell the bad news to zone manager, so that 
+        it can reset the refresh timer for that zone. '''
+        param = {'zone_name': zone_name}
+        if xfr_result == XFRIN_OK:
+            msg = create_command(notify_out.ZONE_NEW_DATA_READY_CMD, param)
+            self._send_cc_session.group_sendmsg(msg, XFROUT_MODULE_NAME)
+            self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
+        else:
+            msg = create_command(ZONE_XFRIN_FAILED, param)
+            self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
+
     def startup(self):
         while not self._shutdown_event.is_set():
             self._cc_check_command()

Modified: branches/trac289/src/bin/xfrin/xfrin.spec.pre.in
==============================================================================
--- branches/trac289/src/bin/xfrin/xfrin.spec.pre.in (original)
+++ branches/trac289/src/bin/xfrin/xfrin.spec.pre.in Wed Aug  4 10:49:38 2010
@@ -8,7 +8,25 @@
         "item_type": "integer",
         "item_optional": false,
         "item_default": 10
-      }
+      },
+      {
+        "item_name": "masters",
+        "item_type": "map",
+        "item_optional": true,
+        "item_default": {},
+        "map_item_spec": [
+           { "item_name": "address",
+             "item_type": "string",
+             "item_optional": false,
+             "item_default": ""
+           },
+           { "item_name": "port",
+             "item_type": "integer",
+             "item_optional": false,
+             "item_default": 53
+           }
+         ]
+       }
     ],
     "commands": [
      {
@@ -29,7 +47,7 @@
           {
             "item_name": "master",
             "item_type": "string",
-            "item_optional": false,
+            "item_optional": true,
             "item_default": ""
           },
           {




More information about the bind10-changes mailing list