update nameserver parsing

git-svn-id: https://linkchecker.svn.sourceforge.net/svnroot/linkchecker/trunk/linkchecker@1103 e7d03fd6-7b0d-0410-9947-9c21f3af8025
This commit is contained in:
calvin 2003-12-18 14:20:37 +00:00
parent 9a76724437
commit b5023d14c4
3 changed files with 207 additions and 175 deletions

View file

@ -10,9 +10,9 @@ This code is covered by the standard Python License.
Base functionality. Request and Response classes, that sort of thing.
"""
import select, socket, string, types, time, asyncore
import select, socket, string, types, time, asyncore, os
class DNSError(Exception): pass
class DNSError (Exception): pass
import Lib, Type, Class, Opcode
@ -27,35 +27,90 @@ defaults = {
'server': [],
}
def ParseResolvConf(resolv_path="/etc/resolv.conf"):
"parses the /etc/resolv.conf file and sets defaults for name servers"
global defaults
lines=open(resolv_path).readlines()
for line in lines:
line = string.strip(line)
if not line or line[0]==';' or line[0]=='#':
continue
fields=string.split(line)
if len(fields) == 0:
continue
if fields[0]=='domain':
defaults['domain']=fields[1]
if fields[0]=='search':
pass
if fields[0]=='options':
pass
if fields[0]=='sortlist':
pass
if fields[0]=='nameserver':
defaults['server'].append(fields[1])
def DiscoverNameServers():
import sys
if sys.platform in ('win32', 'nt'):
import win32dns
defaults['server']=win32dns.RegistryResolve()
def DiscoverNameServers ():
import os
if os.name=='posix':
init_dns_resolver_posix()
elif os.name=='nt':
init_dns_resolver_nt()
else:
return ParseResolvConf()
# other platforms not supported (what about Mac?)
pass
if not defaults['server']:
# last fallback: localhost
defaults['server'].append('127.0.0.1')
def init_dns_resolver_posix ():
"Set up the DnsLookupConnection class with /etc/resolv.conf information"
if not os.path.exists('/etc/resolv.conf'):
return
for line in file('/etc/resolv.conf', 'r').readlines():
line = line.strip()
if (not line) or line[0]==';' or line[0]=='#':
continue
m = re.match(r'^search\s+(\.?.+)$', line)
if m:
for domain in m.group(1).split():
# domain search path not used
pass
m = re.match(r'^nameserver\s+(\S+)\s*$', line)
if m:
defaults['server'].append(m.group(1))
def init_dns_resolver_nt ():
import winreg
key = None
try:
key = winreg.key_handle(winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters")
except EnvironmentError:
try: # for Windows ME
key = winreg.key_handle(winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\VxD\MSTCP")
except EnvironmentError:
pass
if key:
for server in winreg.stringdisplay(key["NameServer"]):
if server:
defaults['server'].append(str(server))
for item in winreg.stringdisplay(key["SearchList"]):
if item:
pass # domain search not used
if not defaults['server']:
# XXX the proper way to test this is to search for
# the "EnableDhcp" key in the interface adapters...
for server in winreg.stringdisplay(key["DhcpNameServer"]):
if server:
defaults['server'].append(str(server))
for item in winreg.stringdisplay(key["DhcpDomain"]):
if item:
pass # domain search not used
try: # search adapters
key = winreg.key_handle(winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DNSRegisteredAdapters")
for subkey in key.subkeys():
count, counttype = subkey['DNSServerAddressCount']
values, valuestype = subkey['DNSServerAddresses']
for server in winreg.binipdisplay(values):
if server:
defaults['server'].append(str(server))
except EnvironmentError:
pass
try: # search interfaces
key = winreg.key_handle(winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces")
for subkey in key.subkeys():
for server in winreg.stringdisplay(subkey.get('NameServer', '')):
if server:
defaults['server'].append(str(server))
except EnvironmentError:
pass
class DnsRequest:
""" high level Request object """
@ -255,6 +310,9 @@ class DnsAsyncRequest(DnsRequest,asyncore.dispatcher_with_send):
#
# $Log$
# Revision 1.7 2003/12/18 14:20:37 calvin
# update nameserver parsing
#
# Revision 1.6 2003/07/04 14:23:22 calvin
# add coding line
#

View file

@ -1,145 +0,0 @@
# -*- coding: iso-8859-1 -*-
"""
$Id$
Extract a list of TCP/IP name servers from the registry 0.1
0.1 Strobl 2001-07-19
Usage:
RegistryResolve() returns a list of ip numbers (dotted quads), by
scouring the registry for addresses of name servers
Tested on Windows NT4 Server SP6a, Windows 2000 Pro SP2 and
Whistler Pro (XP) Build 2462 and Windows ME
... all having a different registry layout wrt name servers :-/
Todo:
Program doesn't check whether an interface is up or down
(c) 2001 Copyright by Wolfgang Strobl ws@mystrobl.de,
License analog to the current Python license
"""
import string, re
import _winreg
def binipdisplay(s):
"convert a binary array of ip adresses to a python list"
if len(s)%4!= 0:
raise EnvironmentError # well ...
ol=[]
for i in range(len(s)/4):
s1=s[:4]
s=s[4:]
ip=[]
for j in s1:
ip.append(str(ord(j)))
ol.append(string.join(ip,'.'))
return ol
def stringdisplay(s):
'''convert "d.d.d.d,d.d.d.d" to ["d.d.d.d","d.d.d.d"].
also handle u'd.d.d.d d.d.d.d', as reporting on SF
'''
import re
return map(str, re.split("[ ,]",s))
def RegistryResolve():
nameservers=[]
x=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
try:
y= _winreg.OpenKey(x,
r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters")
except EnvironmentError: # so it isn't NT/2000/XP
# windows ME, perhaps?
try: # for Windows ME
y= _winreg.OpenKey(x,
r"SYSTEM\CurrentControlSet\Services\VxD\MSTCP")
nameserver,dummytype=_winreg.QueryValueEx(y,'NameServer')
if nameserver and not (nameserver in nameservers):
nameservers.extend(stringdisplay(nameserver))
except EnvironmentError:
pass
return nameservers # no idea
nameserver = _winreg.QueryValueEx(y,"NameServer")[0]
if nameserver:
nameservers=[nameserver]
_winreg.CloseKey(y)
try: # for win2000
y= _winreg.OpenKey(x,
r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DNSRegisteredAdapters")
for i in range(1000):
try:
n=_winreg.EnumKey(y,i)
z=_winreg.OpenKey(y,n)
dnscount,dnscounttype=_winreg.QueryValueEx(z,
'DNSServerAddressCount')
dnsvalues,dnsvaluestype=_winreg.QueryValueEx(z,
'DNSServerAddresses')
nameservers.extend(binipdisplay(dnsvalues))
_winreg.CloseKey(z)
except EnvironmentError:
break
_winreg.CloseKey(y)
except EnvironmentError:
pass
#
try: # for whistler
y= _winreg.OpenKey(x,
r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces")
for i in range(1000):
try:
n=_winreg.EnumKey(y,i)
z=_winreg.OpenKey(y,n)
try:
nameserver,dummytype=_winreg.QueryValueEx(z,'NameServer')
if nameserver and not (nameserver in nameservers):
nameservers.extend(stringdisplay(nameserver))
except EnvironmentError:
pass
_winreg.CloseKey(z)
except EnvironmentError:
break
_winreg.CloseKey(y)
except EnvironmentError:
#print "Key Interfaces not found, just do nothing"
pass
#
_winreg.CloseKey(x)
return nameservers
if __name__=="__main__":
print "Name servers:",RegistryResolve()
#
# $Log$
# Revision 1.2 2003/07/04 14:23:22 calvin
# add coding line
#
# Revision 1.1 2002/11/26 23:27:43 calvin
# update to Python >= 2.2.1
#
# Revision 1.3 2002/05/06 06:15:31 anthonybaxter
# apparently some versions of windows return servers as unicode
# string with space sep, rather than strings with comma sep.
# *sigh*
#
# Revision 1.2 2002/03/19 12:41:33 anthonybaxter
# tabnannied and reindented everything. 4 space indent, no tabs.
# yay.
#
# Revision 1.1 2001/08/09 09:22:28 anthonybaxter
# added what I hope is win32 resolver lookup support. I'll need to try
# and figure out how to get the CVS checkout onto my windows machine to
# make sure it works (wow, doing something other than games on the
# windows machine :)
#
# Code from Wolfgang.Strobl@gmd.de
# win32dns.py from
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66260
#
# Really, ParseResolvConf() should be renamed "FindNameServers" or
# some such.
#
#

119
linkcheck/DNS/winreg.py Normal file
View file

@ -0,0 +1,119 @@
# -*- coding: iso-8859-1 -*-
"""_winreg convenience wrapper (currently readonly)"""
# Copyright (C) 2001 Bastian Kleineidam (except helper functions below)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
__version__ = "$Revision$"[11:-2]
__date__ = "$Date$"[7:-2]
# import all from _winreg
from _winreg import *
from types import StringType
class key_handle (object):
"""represent an opened key with dictionary-like access"""
def __init__ (self, key, sub_key):
self._key = OpenKey(key, sub_key)
self.closed = False
def __getitem__ (self, key):
if type(key) != StringType:
raise TypeError, "key type must be string"
try:
val = QueryValueEx(self._key, key)
except WindowsError:
raise IndexError, "subkey %s not found"%key
return val[0]
def get (self, key, default=None):
try:
return self[key]
except IndexError:
return default
def subkeys (self):
"""get the list of subkeys as key_handle objects"""
i = 0
keys = []
while 1:
try:
#print repr(EnumKey(self._key, i))
keys.append(key_handle(self._key, EnumKey(self._key, i)))
except EnvironmentError:
break
i += 1
return keys
def __len__ (self):
return QueryInfoKey(self._key)[0]
def __setitem__ (self, key, value):
"""Set a registry key value. key is the key name,
value is a tuple (type, val). For available types
see the _winreg module documentation."""
key = self.__getitem__(key)
SetValueEx(self._key, key, value[0], value[1])
def __delitem__ (self, key):
"""XXX to be implemented"""
pass
def close (self):
CloseKey(self._key)
self.closed = True
def __del__ (self):
if not self.closed:
self.close()
#################################################################
# helper functions from pydns at sourceforge
# (c) 2001 Copyright by Wolfgang Strobl ws@mystrobl.de,
# License analog to the current Python license
def binipdisplay (s):
"convert a binary array of ip adresses to a python list"
if len(s)%4!= 0:
raise EnvironmentError # well ...
ol=[]
for i in range(len(s)/4):
s1=s[:4]
s=s[4:]
ip=[]
for j in s1:
ip.append(str(ord(j)))
ol.append('.'.join(ip))
return ol
def stringdisplay (s):
'convert "d.d.d.d,d.d.d.d" to ["d.d.d.d","d.d.d.d"]'
return s.split(",")
#################################################################
def test ():
pass
if __name__=="__main__":
test()