PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Ruby/lib/ruby/2.0.0/win32/resolv.rb

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