Skip to content

Commit 7871b3b

Browse files
committed
* ext/Win32API/lib/win32/resolv.rb: added.
* lib/resolv.rb: support Win32 platforms. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4135 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent f00c14c commit 7871b3b

File tree

4 files changed

+424
-41
lines changed

4 files changed

+424
-41
lines changed

ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
Thu Jul 24 09:58:32 2003 NAKAMURA Usaku <usa@ruby-lang.org>
2+
3+
* ext/Win32API/lib/win32/resolv.rb: added.
4+
5+
* lib/resolv.rb: support Win32 platforms.
6+
17
Thu Jul 24 04:05:46 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
28

39
* ext/openssl/ssl.h: undef X509_NAME and PKCS7_SIGNER_INFO to

ext/Win32API/MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ extconf.rb
66
getch.rb
77
point.rb
88
lib/win32/registry.rb
9+
lib/win32/resolv.rb

ext/Win32API/lib/win32/resolv.rb

Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
=begin
2+
= Win32 DNS and DHCP I/F
3+
4+
=end
5+
6+
require 'win32/registry'
7+
8+
module Win32
9+
module Resolv
10+
API = Registry::API
11+
12+
def self.get_hosts_path
13+
path = get_hosts_dir
14+
path = File.join(path.gsub(/\\/, File::SEPARATOR), 'hosts')
15+
File.exist?(path) ? path : nil
16+
end
17+
18+
def self.get_resolv_info
19+
search, nameserver = get_info
20+
if search.empty?
21+
search = nil
22+
else
23+
search.delete("")
24+
search.uniq!
25+
end
26+
if nameserver.empty?
27+
nameserver = nil
28+
else
29+
nameserver.delete("")
30+
nameserver.delete("0.0.0.0")
31+
nameserver.uniq!
32+
end
33+
[ search, nameserver ]
34+
end
35+
36+
getv = Win32API.new('kernel32.dll', 'GetVersionExA', 'P', 'L')
37+
info = [ 148, 0, 0, 0, 0 ].pack('V5') + "\0" * 128
38+
getv.call(info)
39+
if info.unpack('V5')[4] == 2 # VER_PLATFORM_WIN32_NT
40+
#====================================================================
41+
# Windows NT
42+
#====================================================================
43+
module_eval <<-'__EOS__', __FILE__, __LINE__+1
44+
TCPIP_NT = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'
45+
46+
class << self
47+
private
48+
def get_hosts_dir
49+
Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
50+
reg.read_s_expand('DataBasePath')
51+
end
52+
end
53+
54+
def get_info
55+
search = nil
56+
nameserver = []
57+
Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
58+
begin
59+
slist = reg.read_s('SearchList')
60+
search = slist.split(/,\s*/) unless slist.empty?
61+
rescue Registry::Error
62+
end
63+
64+
if add_search = search.nil?
65+
search = []
66+
begin
67+
nvdom = reg.read_s('NV Domain')
68+
unless nvdom.empty?
69+
@search = [ nvdom ]
70+
if reg.read_i('UseDomainNameDevolution') != 0
71+
if /^[\w\d]+\./ =~ nvdom
72+
devo = $'
73+
end
74+
end
75+
end
76+
rescue Registry::Error
77+
end
78+
end
79+
80+
reg.open('Interfaces') do |reg|
81+
reg.each_key do |iface,|
82+
reg.open(iface) do |regif|
83+
begin
84+
[ 'NameServer', 'DhcpNameServer' ].each do |key|
85+
ns = regif.read_s(key)
86+
unless ns.empty?
87+
nameserver.concat(ns.split(/\s+/))
88+
break
89+
end
90+
end
91+
rescue Registry::Error
92+
end
93+
94+
if add_search
95+
begin
96+
[ 'Domain', 'DhcpDomain' ].each do |key|
97+
dom = regif.read_s(key)
98+
unless dom.empty?
99+
search.concat(dom.split(/,\s*/))
100+
break
101+
end
102+
end
103+
rescue Registry::Error
104+
end
105+
end
106+
end
107+
end
108+
end
109+
search << devo if add_search and devo
110+
end
111+
[ search.uniq, nameserver.uniq ]
112+
end
113+
end
114+
__EOS__
115+
else
116+
#====================================================================
117+
# Windows 9x
118+
#====================================================================
119+
module_eval <<-'__EOS__', __FILE__, __LINE__+1
120+
TCPIP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\MSTCP'
121+
DHCP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\DHCP'
122+
WINDOWS = 'Software\Microsoft\Windows\CurrentVersion'
123+
124+
class << self
125+
# private
126+
127+
def get_hosts_dir
128+
Registry::HKEY_LOCAL_MACHINE.open(WINDOWS) do |reg|
129+
reg.read_s_expand('SystemRoot')
130+
end
131+
end
132+
133+
def get_info
134+
search = []
135+
nameserver = []
136+
begin
137+
Registry::HKEY_LOCAL_MACHINE.open(TCPIP_9X) do |reg|
138+
if reg.read_s("EnableDNS") == "1"
139+
domain = reg.read_s("Domain")
140+
ns = reg.read_s("NameServer")
141+
slist = reg.read_s("SearchList")
142+
search << domain unless domain.empty?
143+
search.concat(slist.split(/,\s*/))
144+
nameserver.concat(ns.split(/,\s*/))
145+
end
146+
end
147+
rescue Registry::Error
148+
end
149+
150+
dhcpinfo = get_dhcpinfo
151+
search.concat(dhcpinfo[0])
152+
nameserver.concat(dhcpinfo[1])
153+
[ search, nameserver ]
154+
end
155+
156+
def get_dhcpinfo
157+
macaddrs = {}
158+
ipaddrs = {}
159+
WsControl.get_iflist.each do |index, macaddr, *ipaddr|
160+
macaddrs[macaddr] = 1
161+
ipaddr.each { |ipaddr| ipaddrs[ipaddr] = 1 }
162+
end
163+
iflist = [ macaddrs, ipaddrs ]
164+
165+
search = []
166+
nameserver = []
167+
version = -1
168+
Registry::HKEY_LOCAL_MACHINE.open(DHCP_9X) do |reg|
169+
begin
170+
version = API.unpackdw(reg.read_bin("Version"))
171+
rescue Registry::Error
172+
end
173+
174+
reg.each_key do |key,|
175+
catch(:not_used) do
176+
reg.open(key) do |regdi|
177+
dom, ns = get_dhcpinfo_key(version, regdi, iflist)
178+
search << dom if dom
179+
nameserver.concat(ns) if ns
180+
end
181+
end
182+
end
183+
end
184+
[ search, nameserver ]
185+
end
186+
187+
def get_dhcpinfo_95(reg)
188+
dhcp = reg.read_bin("DhcpInfo")
189+
[
190+
API.unpackdw(dhcp[4..7]),
191+
API.unpackdw(dhcp[8..11]),
192+
1,
193+
dhcp[45..50],
194+
reg.read_bin("OptionInfo"),
195+
]
196+
end
197+
198+
def get_dhcpinfo_98(reg)
199+
[
200+
API.unpackdw(reg.read_bin("DhcpIPAddress")),
201+
API.unpackdw(reg.read_bin("DhcpSubnetMask")),
202+
API.unpackdw(reg.read_bin("HardwareType")),
203+
reg.read_bin("HardwareAddress"),
204+
reg.read_bin("OptionInfo"),
205+
]
206+
end
207+
208+
def get_dhcpinfo_key(version, reg, iflist)
209+
info = case version
210+
when 1
211+
get_dhcpinfo_95(reg)
212+
when 2
213+
get_dhcpinfo_98(reg)
214+
else
215+
begin
216+
get_dhcpinfo_98(reg)
217+
rescue Registry::Error
218+
get_dhcpinfo_95(reg)
219+
end
220+
end
221+
ipaddr, netmask, hwtype, macaddr, opt = info
222+
throw :not_used unless
223+
ipaddr and ipaddr != 0 and
224+
netmask and netmask != 0 and
225+
macaddr and macaddr.size == 6 and
226+
hwtype == 1 and
227+
iflist[0][macaddr] and iflist[1][ipaddr]
228+
229+
size = opt.size
230+
idx = 0
231+
while idx <= size
232+
opttype = opt[idx]
233+
optsize = opt[idx + 1]
234+
optval = opt[idx + 2, optsize]
235+
case opttype
236+
when 0xFF ## term
237+
break
238+
when 0x0F ## domain
239+
domain = optval.chomp("\0")
240+
when 0x06 ## dns
241+
nameserver = optval.scan(/..../).collect { |addr|
242+
"%d.%d.%d.%d" % addr.unpack('C4')
243+
}
244+
end
245+
idx += optsize + 2
246+
end
247+
[ domain, nameserver ]
248+
rescue Registry::Error
249+
throw :not_used
250+
end
251+
end
252+
253+
module WsControl
254+
WsControl = Win32API.new('wsock32.dll', 'WsControl', 'LLPPPP', 'L')
255+
WSAGetLastError = Win32API.new('wsock32.dll', 'WSAGetLastError', 'V', 'L')
256+
257+
MAX_TDI_ENTITIES = 512
258+
IPPROTO_TCP = 6
259+
WSCTL_TCP_QUERY_INFORMATION = 0
260+
INFO_CLASS_GENERIC = 0x100
261+
INFO_CLASS_PROTOCOL = 0x200
262+
INFO_TYPE_PROVIDER = 0x100
263+
ENTITY_LIST_ID = 0
264+
GENERIC_ENTITY = 0
265+
CL_NL_ENTITY = 0x301
266+
IF_ENTITY = 0x200
267+
ENTITY_TYPE_ID = 1
268+
CL_NL_IP = 0x303
269+
IF_MIB = 0x202
270+
IF_MIB_STATS_ID = 1
271+
IP_MIB_ADDRTABLE_ENTRY_ID = 0x102
272+
273+
def self.wsctl(tei_entity, tei_instance,
274+
toi_class, toi_type, toi_id,
275+
buffsize)
276+
reqinfo = [
277+
## TDIEntityID
278+
tei_entity, tei_instance,
279+
## TDIObjectID
280+
toi_class, toi_type, toi_id,
281+
## TCP_REQUEST_INFORMATION_EX
282+
""
283+
].pack('VVVVVa16')
284+
reqsize = API.packdw(reqinfo.size)
285+
buff = "\0" * buffsize
286+
buffsize = API.packdw(buffsize)
287+
result = WsControl.call(
288+
IPPROTO_TCP,
289+
WSCTL_TCP_QUERY_INFORMATION,
290+
reqinfo, reqsize,
291+
buff, buffsize)
292+
if result != 0
293+
raise RuntimeError, "WsControl failed.(#{result})"
294+
end
295+
[ buff, API.unpackdw(buffsize) ]
296+
end
297+
private_class_method :wsctl
298+
299+
def self.get_iflist
300+
# Get TDI Entity List
301+
entities, size =
302+
wsctl(GENERIC_ENTITY, 0,
303+
INFO_CLASS_GENERIC,
304+
INFO_TYPE_PROVIDER,
305+
ENTITY_LIST_ID,
306+
MAX_TDI_ENTITIES * 8) # sizeof(TDIEntityID)
307+
entities = entities[0, size].
308+
scan(/.{8}/).
309+
collect { |e| e.unpack('VV') }
310+
311+
# Get MIB Interface List
312+
iflist = []
313+
ifcount = 0
314+
entities.each do |entity, instance|
315+
if( (entity & IF_ENTITY)>0 )
316+
ifcount += 1
317+
etype, = wsctl(entity, instance,
318+
INFO_CLASS_GENERIC,
319+
INFO_TYPE_PROVIDER,
320+
ENTITY_TYPE_ID,
321+
4)
322+
if( (API.unpackdw(etype) & IF_MIB)==IF_MIB )
323+
ifentry, = wsctl(entity, instance,
324+
INFO_CLASS_PROTOCOL,
325+
INFO_TYPE_PROVIDER,
326+
IF_MIB_STATS_ID,
327+
21 * 4 + 8 + 130) # sizeof(IFEntry)
328+
iflist << [
329+
API.unpackdw(ifentry[0,4]),
330+
ifentry[20, 6]
331+
]
332+
end
333+
end
334+
end
335+
336+
# Get IP Addresses
337+
entities.each do |entity, instance|
338+
if entity == CL_NL_ENTITY
339+
etype, = wsctl(entity, instance,
340+
INFO_CLASS_GENERIC,
341+
INFO_TYPE_PROVIDER,
342+
ENTITY_TYPE_ID,
343+
4)
344+
if API.unpackdw(etype) == CL_NL_IP
345+
ipentries, = wsctl(entity, instance,
346+
INFO_CLASS_PROTOCOL,
347+
INFO_TYPE_PROVIDER,
348+
IP_MIB_ADDRTABLE_ENTRY_ID,
349+
24 * (ifcount+1)) # sizeof(IPAddrEntry)
350+
ipentries.scan(/.{24}/) do |ipentry|
351+
ipaddr, index = ipentry.unpack('VV')
352+
if ifitem = iflist.assoc(index)
353+
ifitem << ipaddr
354+
end
355+
end
356+
end
357+
end
358+
end
359+
iflist
360+
end
361+
end
362+
__EOS__
363+
end
364+
#====================================================================
365+
end
366+
end

0 commit comments

Comments
 (0)