]> git.ipfire.org Git - oddments/ddns.git/blobdiff - src/ddns/system.py
Add a simple call to resolve a hostname.
[oddments/ddns.git] / src / ddns / system.py
index 6057ef48006b437b1a3786cbfa71c1c6b30c7545..a071e489f1e5850367e150eb52135a8002770ef3 100644 (file)
@@ -19,7 +19,9 @@
 #                                                                             #
 ###############################################################################
 
+import base64
 import re
+import socket
 import urllib
 import urllib2
 
@@ -86,7 +88,7 @@ class DDNSSystem(object):
 
                        return match.group(1)
 
-       def send_request(self, url, method="GET", data=None, timeout=30):
+       def send_request(self, url, method="GET", data=None, username=None, password=None, timeout=30):
                assert method in ("GET", "POST")
 
                # Add all arguments in the data dict to the URL and escape them properly.
@@ -102,6 +104,11 @@ class DDNSSystem(object):
 
                req = urllib2.Request(url, data=data)
 
+               if username and password:
+                       basic_auth_header = self._make_basic_auth_header(username, password)
+                       print repr(basic_auth_header)
+                       req.add_header("Authorization", "Basic %s" % basic_auth_header)
+
                # Set the user agent.
                req.add_header("User-Agent", self.USER_AGENT)
 
@@ -144,6 +151,17 @@ class DDNSSystem(object):
 
                return "&".join(args)
 
+       def _make_basic_auth_header(self, username, password):
+               authstring = "%s:%s" % (username, password)
+
+               # Encode authorization data in base64.
+               authstring = base64.encodestring(authstring)
+
+               # Remove any newline characters.
+               authstring = authstring.replace("\n", "")
+
+               return authstring
+
        def get_address(self, proto):
                assert proto in ("ipv6", "ipv4")
 
@@ -162,3 +180,42 @@ class DDNSSystem(object):
 
                # XXX TODO
                assert False
+
+       def resolve(self, hostname, proto=None):
+               addresses = []
+
+               if proto is None:
+                       family = 0
+               elif proto == "ipv6":
+                       family = socket.AF_INET6
+               elif proto == "ipv4":
+                       family = socket.AF_INET
+               else:
+                       raise ValueError("Protocol not supported: %s" % proto)
+
+               # Resolve the host address.
+               response = socket.getaddrinfo(hostname, None, family)
+
+               # Handle responses.
+               for family, socktype, proto, canonname, sockaddr in response:
+                       # IPv6
+                       if family == socket.AF_INET6:
+                               address, port, flow_info, scope_id = sockaddr
+
+                               # Only use the global scope.
+                               if not scope_id == 0:
+                                       continue
+
+                       # IPv4
+                       elif family == socket.AF_INET:
+                               address, port = sockaddr
+
+                       # Ignore everything else...
+                       else:
+                               continue
+
+                       # Add to repsonse list if not already in there.
+                       if not address in addresses:
+                               addresses.append(address)
+
+               return addresses