[twill] [titus@caltech.edu: [Dnspython-users] dnspython-based extension module for twill.]

Titus Brown titus at caltech.edu
Sun Mar 26 12:15:27 PST 2006


FYI.

----- Forwarded message from Titus Brown <titus at caltech.edu> -----

From: Titus Brown <titus at caltech.edu>
To: halley at dnspython.org
X-Spam-Checker-Version: SpamAssassin 3.0.4 (2005-06-05) on woof.play-bow.org
X-Spam-Level: 
X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham 
	version=3.0.4
Cc: dnspython-users at dnspython.org
Subject: [Dnspython-users] dnspython-based extension module for twill.
X-BeenThere: dnspython-users at dnspython.org
X-Mailman-Version: 2.1.5
Reply-To: titus at idyll.org
List-Id: dnspython users list <dnspython-users.dnspython.org>
List-Unsubscribe: <http://woof.play-bow.org/mailman/listinfo/dnspython-users>, 
	<mailto:dnspython-users-request at dnspython.org?subject=unsubscribe>
List-Archive: <http://woof.play-bow.org/pipermail/dnspython-users>
List-Post: <mailto:dnspython-users at dnspython.org>
List-Help: <mailto:dnspython-users-request at dnspython.org?subject=help>
List-Subscribe: <http://woof.play-bow.org/mailman/listinfo/dnspython-users>,
	<mailto:dnspython-users-request at dnspython.org?subject=subscribe>

Hi all,

as part of my latest Evil Plot to Take Over the World (with twill), I
have added a dnspython-based extension module to my little Python-based
scripting language, twill.

This makes little scriptlets like the following possible:

===
extend_with dns_check

dns_resolves amazon.com 207.171.175.29          # amazon.com ==> any of 3
dns_resolves amazon.com 207.171.166.102
dns_resolves amazon.com 72.21.206.5

dns_resolves idyll.org. 131.215.34.116
dns_resolves idyll.org. joiry.net.              # same IP addr?

dns_mx idyll.org. mail.idyll.org.               # '.'s are handled
dns_mx idyll.org mail.idyll.org.
dns_mx idyll.org. mail.idyll.org

dns_a amazon.com 207.171.175.29                 # explicit 'A' records.
dns_a amazon.com 207.171.166.102
dns_a amazon.com 72.21.206.5

dns_cname www.idyll.org. idyll.org.             # explicit 'CNAME' records.

dns_ns idyll.org nsa.idyll.org
===

Check out my latest blog entry

	http://www.advogato.org/person/titus/diary.html?start=168

for a bit more info, and twill itself at

	http://www.idyll.org/~t/www-tools/twill/

I'd be interested in your comments on the underlying code (attached).  I
freely admit to not knowing what I'm doing; I basically just hacked and
slashed until I got what looked like the right results.  Corrections
and/or comments on the attached code are appreciated & will be
acknowledged.

cheers,
--titus

"""
Extension functions to help query/assert name service information.

Functions:

  * dns_resolves -- assert that a host resolves to a specific IP address.
  * dns_a -- assert that a host directly resolves to a specific IP address
  * dns_cname -- assert that a host is an alias for another hostname.
  * dnx_mx -- assert that a given host is a mail exchanger for the given name.
  * dns_ns -- assert that a given hostname is a name server for the given name.
"""

from twill.errors import TwillAssertionError

try:
    import dns.resolver
except ImportError:
    raise Exception("ERROR: must have dnspython installed to use the DNS extension module")

def dns_a(host, ipaddress, server=None):
    """
    >> dns_a <name> <ipaddress> [<name server>]

    Assert that <name> resolves to <ipaddress> (and is an A record).
    Optionally use the given name server.
    """
    if not is_ip_addr(ipaddress):
        raise Exception("<ipaddress> parameter must be an IP address, not a hostname")

    for answer in _query(host, 'A', server):
        if _compare_hostnames(ipaddress, str(answer)):
            return True

    raise TwillAssertionError

def dns_cname(host, cname, server=None):
    """
    >> dns_cname <name> <alias_for> [<name server>]

    Assert that <name> is a CNAME alias for <alias_for>  Optionally use
    <name server>.
    """
    if is_ip_addr(cname):
        raise Exception("<alias_for> parameter must be a hostname, not an IP address")
    
    for answer in _query(host, 'CNAME', server):
        if _compare_hostnames(cname, str(answer)):
            return True

    raise TwillAssertionError

def dns_resolves(host, ipaddress, server=None):
    """
    >> dns_resolves <name> <name2/ipaddress> [<name server>]
    
    Assert that <name> ultimately resolves to the given IP address (or
    the same IP address that 'name2' resolves to).  Optionally use the
    given name server.
    """
    if not is_ip_addr(ipaddress):
        ipaddress = _resolve_name(ipaddress, server)
        
    for answer in _query(host, 1, server):
        if _compare_hostnames(ipaddress, str(answer)):
            return True

    raise TwillAssertionError

def dns_mx(host, mailserver, server=None):
    """
    >> dns_mx <name> <mailserver> [<name server>]

    Assert that <mailserver> is a mailserver for <name>.
    """
    for rdata in _query(host, 'MX', server):
        (pref, n) = str(rdata).split()

        if _compare_hostnames(n, mailserver):
            return True

    raise TwillAssertionError

def dns_ns(host, query_ns, server=None):
    """
    >>> dns_ns <domain> <nameserver> [<name server to use>]

    Assert that <nameserver> is a mailserver for <domain>.
    """
    for answer in _query(host, 'NS', server):
        if _compare_hostnames(query_ns, str(answer)):
            return True

###

def _compare_hostnames(a, b):
    """
    Normalize two hostnames for string comparison.  (basically strip off
    '.'s ;)
    """
    a = a.strip('.')
    b = b.strip('.')
    return (a == b)

def is_ip_addr(name):
    """
    Check the 'name' to see if it's just an IP address.  Probably should use
    a regexp to do this... @CTB
    """
    name = name.replace('.', '')
    for i in range(0, 10):
        i = str(i)
        name = name.replace(i, '')

    if name:
        return False
    return True

def _resolve_name(name, server):
    """
    Resolve the given name to an IP address.
    """
    if is_ip_addr(name):
        return name
    
    r = dns.resolver.Resolver()
    if server:
        r.nameservers = [_resolve_name(server)]

    answers = r.query(name)

    answer = None
    for answer in answers:              # @CTB !?
        break

    assert answer
    return str(answer)

def _query(query, query_type, server):
    """
    Query, perhaps via the given name server.  (server=None to use default).
    """
    r = dns.resolver.Resolver()
    if server:
        r.nameservers = [_resolve_name(server)]

    return r.query(query, query_type)

_______________________________________________
dnspython-users mailing list
dnspython-users at dnspython.org
http://woof.play-bow.org/mailman/listinfo/dnspython-users


----- End forwarded message -----



More information about the twill mailing list