You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
3.1 KiB
86 lines
3.1 KiB
# Copyright (C) 2006, 2007, 2009, 2011 Nominum, Inc.
|
|
#
|
|
# Permission to use, copy, modify, and distribute this software and its
|
|
# documentation for any purpose with or without fee is hereby granted,
|
|
# provided that the above copyright notice and this permission notice
|
|
# appear in all copies.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
"""DNS E.164 helpers
|
|
|
|
@var public_enum_domain: The DNS public ENUM domain, e164.arpa.
|
|
@type public_enum_domain: dns.name.Name object
|
|
"""
|
|
|
|
|
|
import dns.exception
|
|
import dns.name
|
|
import dns.resolver
|
|
from ._compat import string_types
|
|
|
|
public_enum_domain = dns.name.from_text('e164.arpa.')
|
|
|
|
|
|
def from_e164(text, origin=public_enum_domain):
|
|
"""Convert an E.164 number in textual form into a Name object whose
|
|
value is the ENUM domain name for that number.
|
|
@param text: an E.164 number in textual form.
|
|
@type text: str
|
|
@param origin: The domain in which the number should be constructed.
|
|
The default is e164.arpa.
|
|
@type origin: dns.name.Name object or None
|
|
@rtype: dns.name.Name object
|
|
"""
|
|
parts = [d for d in text if d.isdigit()]
|
|
parts.reverse()
|
|
return dns.name.from_text('.'.join(parts), origin=origin)
|
|
|
|
|
|
def to_e164(name, origin=public_enum_domain, want_plus_prefix=True):
|
|
"""Convert an ENUM domain name into an E.164 number.
|
|
@param name: the ENUM domain name.
|
|
@type name: dns.name.Name object.
|
|
@param origin: A domain containing the ENUM domain name. The
|
|
name is relativized to this domain before being converted to text.
|
|
@type origin: dns.name.Name object or None
|
|
@param want_plus_prefix: if True, add a '+' to the beginning of the
|
|
returned number.
|
|
@rtype: str
|
|
"""
|
|
if origin is not None:
|
|
name = name.relativize(origin)
|
|
dlabels = [d for d in name.labels if d.isdigit() and len(d) == 1]
|
|
if len(dlabels) != len(name.labels):
|
|
raise dns.exception.SyntaxError('non-digit labels in ENUM domain name')
|
|
dlabels.reverse()
|
|
text = b''.join(dlabels)
|
|
if want_plus_prefix:
|
|
text = b'+' + text
|
|
return text
|
|
|
|
|
|
def query(number, domains, resolver=None):
|
|
"""Look for NAPTR RRs for the specified number in the specified domains.
|
|
|
|
e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.'])
|
|
"""
|
|
if resolver is None:
|
|
resolver = dns.resolver.get_default_resolver()
|
|
e_nx = dns.resolver.NXDOMAIN()
|
|
for domain in domains:
|
|
if isinstance(domain, string_types):
|
|
domain = dns.name.from_text(domain)
|
|
qname = dns.e164.from_e164(number, domain)
|
|
try:
|
|
return resolver.query(qname, 'NAPTR')
|
|
except dns.resolver.NXDOMAIN as e:
|
|
e_nx += e
|
|
raise e_nx
|