From f7cec864e34f59109018b47f4efd4f7314c817d2 Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Fri, 14 May 2010 14:35:18 +0000 Subject: [PATCH] added manual python wrappers location to PYTHONPATH made xfrout use the dns python wrappers instead of the boost.python one (still needs boost.python for the wrappers for sending sockets around) also fixed a few other problems in xfrout; - UNIX_SOCKET_FILE (the socket that is used to send other socket descriptors over) only worked if installed, updated to use @abs_top_srcdir@/auth_sock_conn for the domain socket file (for now, where should we really put this?) Also updated bin/auth/main.cc to use this one if run from source tree - That file descriptor that is passed wasn't closed, so after a while the system would run out of file descriptors. Added os.close(fd) for that to xfrout. We might want to think about adding this to our send_fd/recv_fd lib - Other (temporary) workaround; When the AXFR response is rendered, it triggers truncation. So for now I used renderer.setLengthLimit(65535). But we might want to simply make multiple message packets within the stream. (all three of these problems also occur in trunk/ btw, but since all of them might be temporary and i'm focusing on the main wrappers here, i committed them here for now) git-svn-id: svn://bind10.isc.org/svn/bind10/experiments/python-binding@1828 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/auth/main.cc | 11 +++- src/bin/bind10/run_bind10.sh.in | 2 +- src/bin/xfrout/run_b10-xfrout.sh.in | 2 +- src/bin/xfrout/xfrout.py.in | 84 +++++++++++++++-------------- 4 files changed, 56 insertions(+), 43 deletions(-) diff --git a/src/bin/auth/main.cc b/src/bin/auth/main.cc index 1203a9cb4..3dcc6b848 100644 --- a/src/bin/auth/main.cc +++ b/src/bin/auth/main.cc @@ -130,7 +130,16 @@ check_axfr_query(char *msg_data, uint16_t msg_len) static void dispatch_axfr_query(int tcp_sock, char axfr_query[], uint16_t query_len) { - std::string path = string(UNIX_SOCKET_FILE); + std::string path; + if (getenv("B10_FROM_SOURCE")) { + path = string(getenv("B10_FROM_SOURCE")) + + "/auth_xfrout_conn"; + } else { + path = string(UNIX_SOCKET_FILE); + } + (void)tcp_sock; + (void)axfr_query; + (void)query_len; XfroutClient xfr_client(path); try { xfr_client.connect(); diff --git a/src/bin/bind10/run_bind10.sh.in b/src/bin/bind10/run_bind10.sh.in index 2218c12fe..99392df48 100644 --- a/src/bin/bind10/run_bind10.sh.in +++ b/src/bin/bind10/run_bind10.sh.in @@ -23,7 +23,7 @@ BIND10_PATH=@abs_top_builddir@/src/bin/bind10 PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:$PATH export PATH -PYTHONPATH=@abs_top_builddir@/src/lib/python +PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs export PYTHONPATH B10_FROM_SOURCE=@abs_top_srcdir@ diff --git a/src/bin/xfrout/run_b10-xfrout.sh.in b/src/bin/xfrout/run_b10-xfrout.sh.in index 1a3a5987e..2bbd208f3 100644 --- a/src/bin/xfrout/run_b10-xfrout.sh.in +++ b/src/bin/xfrout/run_b10-xfrout.sh.in @@ -19,7 +19,7 @@ PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@} export PYTHON_EXEC MYPATH_PATH=@abs_top_builddir@/src/bin/xfrout -PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/xfr/.libs +PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/dns/python/.libs export PYTHONPATH cd ${MYPATH_PATH} diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index 7099bf1e9..b9d958f59 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -31,7 +31,7 @@ import socket from optparse import OptionParser, OptionValueError try: from bind10_xfr import * - from bind10_dns import * + from libdns_python import * except ImportError as e: # C++ loadable module may not be installed; even so the xfrout process # must keep running, so we warn about it and move forward. @@ -39,12 +39,13 @@ except ImportError as e: if "B10_FROM_SOURCE" in os.environ: SPECFILE_PATH = os.environ["B10_FROM_SOURCE"] + "/src/bin/xfrout" + UNIX_SOCKET_FILE = os.environ["B10_FROM_SOURCE"] + "/auth_xfrout_conn" else: PREFIX = "@prefix@" DATAROOTDIR = "@datarootdir@" SPECFILE_PATH = "@datadir@/@PACKAGE@".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX) + UNIX_SOCKET_FILE = "@localstatedir@".replace("${prefix}", PREFIX) + "/auth_xfrout_conn" SPECFILE_LOCATION = SPECFILE_PATH + "/xfrout.spec" -UNIX_SOCKET_FILE = "@localstatedir@".replace("${prefix}", PREFIX) + "/auth_xfrout_conn" MAX_TRANSFERS_OUT = 10 verbose_mode = False @@ -52,10 +53,10 @@ verbose_mode = False class XfroutException(Exception): pass - class XfroutSession(BaseRequestHandler): def handle(self): fd = recv_fd(self.request.fileno()) + if fd < 0: raise XfroutException("failed to receive the FD for XFR connection") data_len = self.request.recv(2) @@ -68,24 +69,26 @@ class XfroutSession(BaseRequestHandler): if verbose_mode: self.log_msg(str(e)) + sock.shutdown(socket.SHUT_RDWR) sock.close() + os.close(fd) + pass def _parse_query_message(self, mdata): ''' parse query message to [socket,message]''' #TODO, need to add parseHeader() in case the message header is invalid try: - msg = message(message_mode.PARSE) - msg.from_wire(input_buffer(mdata)) + msg = Message(PARSE) + msg.from_wire(mdata) except Exception as err: if verbose_mode: self.log_msg(str(err)) - return rcode.FORMERR(), None + return Rcode.FORMERR(), None - return rcode.NOERROR(), msg + return Rcode.NOERROR(), msg def _get_query_zone_name(self, msg): - q_iter = question_iter(msg) - question = q_iter.get_question() + question = msg.get_question()[0] return question.get_name().to_text() @@ -98,12 +101,14 @@ class XfroutSession(BaseRequestHandler): def _send_message(self, sock, msg): - obuf = output_buffer(0) - render = message_render(obuf) + #obuf = output_buffer(0) + #render = message_render(obuf) + render = MessageRenderer() + render.set_length_limit(65535) msg.to_wire(render) - header_len = struct.pack('H', socket.htons(obuf.get_length())) + header_len = struct.pack('H', socket.htons(render.get_length())) self._send_data(sock, header_len) - self._send_data(sock, obuf.get_data()) + self._send_data(sock, render.get_data()) def _reply_query_with_error_rcode(self, msg, sock, rcode_): @@ -118,7 +123,7 @@ class XfroutSession(BaseRequestHandler): return # query message is invalid. send nothing back. msg.make_response() - msg.set_rcode(rcode.FORMERR()) + msg.set_rcode(Rcode.FORMERR()) self._send_message(sock, msg) @@ -143,27 +148,27 @@ class XfroutSession(BaseRequestHandler): eg. check allow_transfer setting, ''' if not self._zone_exist(zone_name): - return rcode.NOTAUTH() + return Rcode.NOTAUTH() if self._zone_is_empty(zone_name): - return rcode.SERVFAIL() + return Rcode.SERVFAIL() #TODO, check allow_transfer if not self.server.increase_transfers_counter(): - return rcode.REFUSED() + return Rcode.REFUSED() - return rcode.NOERROR() + return Rcode.NOERROR() def dns_xfrout_start(self, sock, msg_query): rcode_, msg = self._parse_query_message(msg_query) #TODO. create query message and parse header - if rcode_ != rcode.NOERROR(): + if rcode_ != Rcode.NOERROR(): return self._reply_query_with_format_error(msg, sock) zone_name = self._get_query_zone_name(msg) rcode_ = self._check_xfrout_available(zone_name) - if rcode_ != rcode.NOERROR(): + if rcode_ != Rcode.NOERROR(): return self. _reply_query_with_error_rcode(msg, sock, rcode_) try: @@ -187,21 +192,21 @@ class XfroutSession(BaseRequestHandler): opcode = msg.get_opcode() rcode = msg.get_rcode() - msg.clear(message_mode.RENDER) + msg.clear(RENDER) msg.set_qid(qid) msg.set_opcode(opcode) msg.set_rcode(rcode) - msg.set_header_flag(message_flag.AA()) - msg.set_header_flag(message_flag.QR()) + msg.set_header_flag(MessageFlag.AA()) + msg.set_header_flag(MessageFlag.QR()) return msg def _create_rrset_from_db_record(self, record): '''Create one rrset from one record of datasource, if the schema of record is changed, This function should be updated first. ''' - rrtype_ = rr_type(record[5]) - rdata_ = create_rdata(rrtype_, rr_class.IN(), " ".join(record[7:])) - rrset_ = rrset(name(record[2]), rr_class.IN(), rrtype_, rr_ttl( int(record[4]))) + rrtype_ = RRType(record[5]) + rdata_ = Rdata(rrtype_, RRClass("IN"), " ".join(record[7:])) + rrset_ = RRset(Name(record[2]), RRClass("IN"), rrtype_, RRTTL( int(record[4]))) rrset_.add_rdata(rdata_) return rrset_ @@ -210,20 +215,19 @@ class XfroutSession(BaseRequestHandler): added, a new message should be created to send out the last soa . ''' - obuf = output_buffer(0) - render = message_render(obuf) + render = MessageRenderer() msg.to_wire(render) - old_message_len = obuf.get_length() - msg.add_rrset(section.ANSWER(), rrset_soa) + old_message_len = render.get_length() + msg.add_rrset(Section.ANSWER(), rrset_soa) msg.to_wire(render) - message_len = obuf.get_length() + message_len = render.get_length() if message_len != old_message_len: self._send_message(sock, msg) else: msg = self._clear_message(msg) - msg.add_rrset(section.ANSWER(), rrset_soa) + msg.add_rrset(Section.ANSWER(), rrset_soa) self._send_message(sock, msg) def _get_message_len(self, msg): @@ -231,19 +235,18 @@ class XfroutSession(BaseRequestHandler): a better way, I need check with jinmei later. ''' - obuf = output_buffer(0) - render = message_render(obuf) + render = MessageRenderer() msg.to_wire(render) - return obuf.get_length() + return render.get_length() def _reply_xfrout_query(self, msg, sock, zone_name): #TODO, there should be a better way to insert rrset. msg.make_response() - msg.set_header_flag(message_flag.AA()) + msg.set_header_flag(MessageFlag.AA()) soa_record = sqlite3_ds.get_zone_soa(zone_name, self.server.get_db_file()) rrset_soa = self._create_rrset_from_db_record(soa_record) - msg.add_rrset(section.ANSWER(), rrset_soa) + msg.add_rrset(Section.ANSWER(), rrset_soa) old_message_len = 0 # TODO, Since add_rrset() return nothing when rrset can't be added, so I have to compare @@ -252,11 +255,12 @@ class XfroutSession(BaseRequestHandler): if self.server._shutdown_event.is_set(): # Check if xfrout is shutdown raise XfroutException("shutdown!") - if rr_type(rr_data[5]) == rr_type.SOA(): #ignore soa record + # TODO: RRType.SOA() ? + if RRType(rr_data[5]) == RRType("SOA"): #ignore soa record continue rrset_ = self._create_rrset_from_db_record(rr_data) - msg.add_rrset(section.ANSWER(), rrset_) + msg.add_rrset(Section.ANSWER(), rrset_) message_len = self._get_message_len(msg) if message_len != old_message_len: old_message_len = message_len @@ -264,7 +268,7 @@ class XfroutSession(BaseRequestHandler): self._send_message(sock, msg) msg = self._clear_message(msg) - msg.add_rrset(section.ANSWER(), rrset_) # Add the rrset to the new message + msg.add_rrset(Section.ANSWER(), rrset_) # Add the rrset to the new message old_message_len = 0 self._send_message_with_last_soa(msg, sock, rrset_soa) -- GitLab