def test_v4(self): self.assertEqual("127.0.0.1:123", str(AddressFormatter(("127.0.0.1", 123)))) self.assertEqual("127.0.0.1:123", str(AddressFormatter(("127.0.0.1", 123), None))) self.assertEqual("192.0.2.1:1", str(AddressFormatter( ("192.0.2.1", 1))))
def _send_notify_message_udp(self, zone_notify_info, addrinfo): msg, qid = self._create_notify_message( Name(zone_notify_info.zone_name), RRClass(zone_notify_info.zone_class)) render = MessageRenderer() render.set_length_limit(512) msg.to_wire(render) zone_notify_info.notify_msg_id = qid try: sock = zone_notify_info.create_socket(addrinfo[0]) sock.sendto(render.get_data(), 0, addrinfo) # count notifying by IPv4 or IPv6 for statistics if self._counters is not None: if zone_notify_info.get_socket().family == socket.AF_INET: self._counters.inc('zones', zone_notify_info.zone_class, zone_notify_info.zone_name, 'notifyoutv4') elif zone_notify_info.get_socket().family == socket.AF_INET6: self._counters.inc('zones', zone_notify_info.zone_class, zone_notify_info.zone_name, 'notifyoutv6') logger.info(NOTIFY_OUT_SENDING_NOTIFY, AddressFormatter(addrinfo)) except (socket.error, addr.InvalidAddress) as err: logger.error(NOTIFY_OUT_SOCKET_ERROR, AddressFormatter(addrinfo), err) return False except addr.InvalidAddress as iae: logger.error(NOTIFY_OUT_INVALID_ADDRESS, AddressFormatter(addrinfo), iae) return False return True
def test_force_family_bad(self): """ These results are 'bad' as in they don't return the value as specified by our guidelines, since the internal check is skipped if the family is given """ self.assertEqual( "[127.0.0.1]:123", str(AddressFormatter(("127.0.0.1", 123), socket.AF_INET6))) self.assertEqual("::1:123", str(AddressFormatter(("::1", 123), socket.AF_INET)))
def _zone_notify_handler(self, zone_notify_info, event_type): """Notify handler for one zone. For the event type of _EVENT_READ, this method reads a new notify response message from the corresponding socket. If it succeeds and the response is the expected one, it will send another notify to the next slave for the zone (if any) or the next zone (if any) waiting for its turn of sending notifies. In the case of _EVENT_TIMEOUT, or if the read fails or the response is not an expected one in the case of _EVENT_READ, this method will resend the notify request to the same slave up to _MAX_NOTIFY_TRY_NUM times. If it reaches the max, it will swith to the next slave or the next zone like the successful case above. The first notify message is always triggered by the event "_EVENT_TIMEOUT" since when one zone prepares to notify its slaves, its notify_timeout is set to now, which is used to trigger sending notify message when dispatcher() scanning zones. Parameters: zone_notify_info(ZoneNotifyInfo): the notify context for the event event_type(int): either _EVENT_READ or _EVENT_TIMEOUT constant """ tgt = zone_notify_info.get_current_notify_target() if event_type == _EVENT_READ: # Note: _get_notify_reply() should also check the response's # source address (see #2924). When it's done the following code # should also be adjusted a bit. reply = self._get_notify_reply(zone_notify_info.get_socket(), tgt) if reply is not None: if (self._handle_notify_reply(zone_notify_info, reply, tgt) == _REPLY_OK): self._notify_next_target(zone_notify_info) else: assert event_type == _EVENT_TIMEOUT if zone_notify_info.notify_try_num > 0: logger.info(NOTIFY_OUT_TIMEOUT, AddressFormatter(tgt)) tgt = zone_notify_info.get_current_notify_target() if tgt: zone_notify_info.notify_try_num += 1 if zone_notify_info.notify_try_num > _MAX_NOTIFY_TRY_NUM: logger.warn(NOTIFY_OUT_RETRY_EXCEEDED, AddressFormatter(tgt), _MAX_NOTIFY_TRY_NUM) self._notify_next_target(zone_notify_info) else: # set exponential backoff according to rfc1996 section 3.6 retry_timeout = (_NOTIFY_TIMEOUT * pow(2, zone_notify_info.notify_try_num)) zone_notify_info.notify_timeout = time.time() + retry_timeout self._send_notify_message_udp(zone_notify_info, tgt)
def _get_notify_reply(self, sock, tgt_addr): try: msg, addr = sock.recvfrom(512) except socket.error as err: logger.error(NOTIFY_OUT_SOCKET_RECV_ERROR, AddressFormatter(tgt_addr), err) return None return msg
def _handle_notify_reply(self, zone_notify_info, msg_data, from_addr): """Parse the notify reply message. rcode will not be checked here; if we get the response from the slave, it means the slave got the notify. """ msg = Message(Message.PARSE) try: msg.from_wire(msg_data) if not msg.get_header_flag(Message.HEADERFLAG_QR): logger.warn(NOTIFY_OUT_REPLY_QR_NOT_SET, AddressFormatter(from_addr)) return _BAD_QR if msg.get_qid() != zone_notify_info.notify_msg_id: logger.warn(NOTIFY_OUT_REPLY_BAD_QID, AddressFormatter(from_addr), msg.get_qid(), zone_notify_info.notify_msg_id) return _BAD_QUERY_ID question = msg.get_question()[0] if question.get_name() != Name(zone_notify_info.zone_name): logger.warn(NOTIFY_OUT_REPLY_BAD_QUERY_NAME, AddressFormatter(from_addr), question.get_name().to_text(), Name(zone_notify_info.zone_name).to_text()) return _BAD_QUERY_NAME if msg.get_opcode() != Opcode.NOTIFY: logger.warn(NOTIFY_OUT_REPLY_BAD_OPCODE, AddressFormatter(from_addr), msg.get_opcode().to_text()) return _BAD_OPCODE except Exception as err: # We don't care what exception, just report it? logger.error(NOTIFY_OUT_REPLY_UNCAUGHT_EXCEPTION, err) return _BAD_REPLY_PACKET logger.debug(logger.DBGLVL_TRACE_BASIC, NOTIFY_OUT_REPLY_RECEIVED, zone_notify_info.zone_name, zone_notify_info.zone_class, AddressFormatter(from_addr), msg.get_rcode()) return _REPLY_OK
def test_bad_values(self): self.assertRaises(ValueError, str, AddressFormatter("string")) self.assertRaises(ValueError, str, AddressFormatter(None)) self.assertRaises(ValueError, str, AddressFormatter(1)) self.assertRaises(ValueError, str, AddressFormatter(("::1", 123), 1)) self.assertRaises(ValueError, str, AddressFormatter(("::1", 123), 1))
def test_force_family_good(self): self.assertEqual( "127.0.0.1:123", str(AddressFormatter(("127.0.0.1", 123), socket.AF_INET))) self.assertEqual("[::1]:123", str(AddressFormatter(("::1", 123), socket.AF_INET6)))
def test_v6(self): self.assertEqual("[::1]:123", str(AddressFormatter(("::1", 123)))) self.assertEqual("[::1]:123", str(AddressFormatter(("::1", 123), None))) self.assertEqual("[2001:db8::]:1", str(AddressFormatter(("2001:db8::", 1))))