PageRenderTime 61ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/TDDBC_Yokohama2_PCUnit/Ruby/lib/ruby/1.9.1/ipaddr.rb

https://bitbucket.org/aetos/tddbc_yokohama2
Ruby | 850 lines | 766 code | 50 blank | 34 comment | 35 complexity | cedf0bc5d3148ae13847d2ec4da5dea7 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, AGPL-3.0, 0BSD, Unlicense
  1. #
  2. # ipaddr.rb - A class to manipulate an IP address
  3. #
  4. # Copyright (c) 2002 Hajimu UMEMOTO <ume@mahoroba.org>.
  5. # Copyright (c) 2007 Akinori MUSHA <knu@iDaemons.org>.
  6. # All rights reserved.
  7. #
  8. # You can redistribute and/or modify it under the same terms as Ruby.
  9. #
  10. # $Id: ipaddr.rb 27000 2010-03-21 12:10:53Z akr $
  11. #
  12. # Contact:
  13. # - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
  14. #
  15. # TODO:
  16. # - scope_id support
  17. #
  18. require 'socket'
  19. unless Socket.const_defined? "AF_INET6"
  20. class Socket < BasicSocket
  21. AF_INET6 = Object.new
  22. end
  23. class << IPSocket
  24. def valid_v4?(addr)
  25. if /\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\Z/ =~ addr
  26. return $~.captures.all? {|i| i.to_i < 256}
  27. end
  28. return false
  29. end
  30. def valid_v6?(addr)
  31. # IPv6 (normal)
  32. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*\Z/ =~ addr
  33. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*)?\Z/ =~ addr
  34. return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*)?\Z/ =~ addr
  35. # IPv6 (IPv4 compat)
  36. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:/ =~ addr && valid_v4?($')
  37. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:)?/ =~ addr && valid_v4?($')
  38. return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:)?/ =~ addr && valid_v4?($')
  39. false
  40. end
  41. def valid?(addr)
  42. valid_v4?(addr) || valid_v6?(addr)
  43. end
  44. alias getaddress_orig getaddress
  45. def getaddress(s)
  46. if valid?(s)
  47. s
  48. elsif /\A[-A-Za-z\d.]+\Z/ =~ s
  49. getaddress_orig(s)
  50. else
  51. raise ArgumentError, "invalid address"
  52. end
  53. end
  54. end
  55. end
  56. # IPAddr provides a set of methods to manipulate an IP address. Both IPv4 and
  57. # IPv6 are supported.
  58. #
  59. # == Example
  60. #
  61. # require 'ipaddr'
  62. #
  63. # ipaddr1 = IPAddr.new "3ffe:505:2::1"
  64. #
  65. # p ipaddr1 #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
  66. #
  67. # p ipaddr1.to_s #=> "3ffe:505:2::1"
  68. #
  69. # ipaddr2 = ipaddr1.mask(48) #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>
  70. #
  71. # p ipaddr2.to_s #=> "3ffe:505:2::"
  72. #
  73. # ipaddr3 = IPAddr.new "192.168.2.0/24"
  74. #
  75. # p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
  76. class IPAddr
  77. IN4MASK = 0xffffffff
  78. IN6MASK = 0xffffffffffffffffffffffffffffffff
  79. IN6FORMAT = (["%.4x"] * 8).join(':')
  80. # Returns the address family of this IP address.
  81. attr_reader :family
  82. # Creates a new ipaddr containing the given network byte ordered
  83. # string form of an IP address.
  84. def IPAddr::new_ntoh(addr)
  85. return IPAddr.new(IPAddr::ntop(addr))
  86. end
  87. # Convert a network byte ordered string form of an IP address into
  88. # human readable form.
  89. def IPAddr::ntop(addr)
  90. case addr.size
  91. when 4
  92. s = addr.unpack('C4').join('.')
  93. when 16
  94. s = IN6FORMAT % addr.unpack('n8')
  95. else
  96. raise ArgumentError, "unsupported address family"
  97. end
  98. return s
  99. end
  100. # Returns a new ipaddr built by bitwise AND.
  101. def &(other)
  102. return self.clone.set(@addr & coerce_other(other).to_i)
  103. end
  104. # Returns a new ipaddr built by bitwise OR.
  105. def |(other)
  106. return self.clone.set(@addr | coerce_other(other).to_i)
  107. end
  108. # Returns a new ipaddr built by bitwise right-shift.
  109. def >>(num)
  110. return self.clone.set(@addr >> num)
  111. end
  112. # Returns a new ipaddr built by bitwise left shift.
  113. def <<(num)
  114. return self.clone.set(addr_mask(@addr << num))
  115. end
  116. # Returns a new ipaddr built by bitwise negation.
  117. def ~
  118. return self.clone.set(addr_mask(~@addr))
  119. end
  120. # Returns true if two ipaddrs are equal.
  121. def ==(other)
  122. other = coerce_other(other)
  123. return @family == other.family && @addr == other.to_i
  124. end
  125. # Returns a new ipaddr built by masking IP address with the given
  126. # prefixlen/netmask. (e.g. 8, 64, "255.255.255.0", etc.)
  127. def mask(prefixlen)
  128. return self.clone.mask!(prefixlen)
  129. end
  130. # Returns true if the given ipaddr is in the range.
  131. #
  132. # e.g.:
  133. # require 'ipaddr'
  134. # net1 = IPAddr.new("192.168.2.0/24")
  135. # net2 = IPAddr.new("192.168.2.100")
  136. # net3 = IPAddr.new("192.168.3.0")
  137. # p net1.include?(net2) #=> true
  138. # p net1.include?(net3) #=> false
  139. def include?(other)
  140. other = coerce_other(other)
  141. if ipv4_mapped?
  142. if (@mask_addr >> 32) != 0xffffffffffffffffffffffff
  143. return false
  144. end
  145. mask_addr = (@mask_addr & IN4MASK)
  146. addr = (@addr & IN4MASK)
  147. family = Socket::AF_INET
  148. else
  149. mask_addr = @mask_addr
  150. addr = @addr
  151. family = @family
  152. end
  153. if other.ipv4_mapped?
  154. other_addr = (other.to_i & IN4MASK)
  155. other_family = Socket::AF_INET
  156. else
  157. other_addr = other.to_i
  158. other_family = other.family
  159. end
  160. if family != other_family
  161. return false
  162. end
  163. return ((addr & mask_addr) == (other_addr & mask_addr))
  164. end
  165. alias === include?
  166. # Returns the integer representation of the ipaddr.
  167. def to_i
  168. return @addr
  169. end
  170. # Returns a string containing the IP address representation.
  171. def to_s
  172. str = to_string
  173. return str if ipv4?
  174. str.gsub!(/\b0{1,3}([\da-f]+)\b/i, '\1')
  175. loop do
  176. break if str.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
  177. break if str.sub!(/\b0:0:0:0:0:0:0\b/, ':')
  178. break if str.sub!(/\b0:0:0:0:0:0\b/, ':')
  179. break if str.sub!(/\b0:0:0:0:0\b/, ':')
  180. break if str.sub!(/\b0:0:0:0\b/, ':')
  181. break if str.sub!(/\b0:0:0\b/, ':')
  182. break if str.sub!(/\b0:0\b/, ':')
  183. break
  184. end
  185. str.sub!(/:{3,}/, '::')
  186. if /\A::(ffff:)?([\da-f]{1,4}):([\da-f]{1,4})\Z/i =~ str
  187. str = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256)
  188. end
  189. str
  190. end
  191. # Returns a string containing the IP address representation in
  192. # canonical form.
  193. def to_string
  194. return _to_string(@addr)
  195. end
  196. # Returns a network byte ordered string form of the IP address.
  197. def hton
  198. case @family
  199. when Socket::AF_INET
  200. return [@addr].pack('N')
  201. when Socket::AF_INET6
  202. return (0..7).map { |i|
  203. (@addr >> (112 - 16 * i)) & 0xffff
  204. }.pack('n8')
  205. else
  206. raise "unsupported address family"
  207. end
  208. end
  209. # Returns true if the ipaddr is an IPv4 address.
  210. def ipv4?
  211. return @family == Socket::AF_INET
  212. end
  213. # Returns true if the ipaddr is an IPv6 address.
  214. def ipv6?
  215. return @family == Socket::AF_INET6
  216. end
  217. # Returns true if the ipaddr is an IPv4-mapped IPv6 address.
  218. def ipv4_mapped?
  219. return ipv6? && (@addr >> 32) == 0xffff
  220. end
  221. # Returns true if the ipaddr is an IPv4-compatible IPv6 address.
  222. def ipv4_compat?
  223. if !ipv6? || (@addr >> 32) != 0
  224. return false
  225. end
  226. a = (@addr & IN4MASK)
  227. return a != 0 && a != 1
  228. end
  229. # Returns a new ipaddr built by converting the native IPv4 address
  230. # into an IPv4-mapped IPv6 address.
  231. def ipv4_mapped
  232. if !ipv4?
  233. raise ArgumentError, "not an IPv4 address"
  234. end
  235. return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
  236. end
  237. # Returns a new ipaddr built by converting the native IPv4 address
  238. # into an IPv4-compatible IPv6 address.
  239. def ipv4_compat
  240. if !ipv4?
  241. raise ArgumentError, "not an IPv4 address"
  242. end
  243. return self.clone.set(@addr, Socket::AF_INET6)
  244. end
  245. # Returns a new ipaddr built by converting the IPv6 address into a
  246. # native IPv4 address. If the IP address is not an IPv4-mapped or
  247. # IPv4-compatible IPv6 address, returns self.
  248. def native
  249. if !ipv4_mapped? && !ipv4_compat?
  250. return self
  251. end
  252. return self.clone.set(@addr & IN4MASK, Socket::AF_INET)
  253. end
  254. # Returns a string for DNS reverse lookup. It returns a string in
  255. # RFC3172 form for an IPv6 address.
  256. def reverse
  257. case @family
  258. when Socket::AF_INET
  259. return _reverse + ".in-addr.arpa"
  260. when Socket::AF_INET6
  261. return ip6_arpa
  262. else
  263. raise "unsupported address family"
  264. end
  265. end
  266. # Returns a string for DNS reverse lookup compatible with RFC3172.
  267. def ip6_arpa
  268. if !ipv6?
  269. raise ArgumentError, "not an IPv6 address"
  270. end
  271. return _reverse + ".ip6.arpa"
  272. end
  273. # Returns a string for DNS reverse lookup compatible with RFC1886.
  274. def ip6_int
  275. if !ipv6?
  276. raise ArgumentError, "not an IPv6 address"
  277. end
  278. return _reverse + ".ip6.int"
  279. end
  280. # Returns the successor to the ipaddr.
  281. def succ
  282. return self.clone.set(@addr + 1, @family)
  283. end
  284. # Compares the ipaddr with another.
  285. def <=>(other)
  286. other = coerce_other(other)
  287. return nil if other.family != @family
  288. return @addr <=> other.to_i
  289. end
  290. include Comparable
  291. # Checks equality used by Hash.
  292. def eql?(other)
  293. return self.class == other.class && self.hash == other.hash && self == other
  294. end
  295. # Returns a hash value used by Hash, Set, and Array classes
  296. def hash
  297. return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1)
  298. end
  299. # Creates a Range object for the network address.
  300. def to_range
  301. begin_addr = (@addr & @mask_addr)
  302. case @family
  303. when Socket::AF_INET
  304. end_addr = (@addr | (IN4MASK ^ @mask_addr))
  305. when Socket::AF_INET6
  306. end_addr = (@addr | (IN6MASK ^ @mask_addr))
  307. else
  308. raise "unsupported address family"
  309. end
  310. return clone.set(begin_addr, @family)..clone.set(end_addr, @family)
  311. end
  312. # Returns a string containing a human-readable representation of the
  313. # ipaddr. ("#<IPAddr: family:address/mask>")
  314. def inspect
  315. case @family
  316. when Socket::AF_INET
  317. af = "IPv4"
  318. when Socket::AF_INET6
  319. af = "IPv6"
  320. else
  321. raise "unsupported address family"
  322. end
  323. return sprintf("#<%s: %s:%s/%s>", self.class.name,
  324. af, _to_string(@addr), _to_string(@mask_addr))
  325. end
  326. protected
  327. def set(addr, *family)
  328. case family[0] ? family[0] : @family
  329. when Socket::AF_INET
  330. if addr < 0 || addr > IN4MASK
  331. raise ArgumentError, "invalid address"
  332. end
  333. when Socket::AF_INET6
  334. if addr < 0 || addr > IN6MASK
  335. raise ArgumentError, "invalid address"
  336. end
  337. else
  338. raise ArgumentError, "unsupported address family"
  339. end
  340. @addr = addr
  341. if family[0]
  342. @family = family[0]
  343. end
  344. return self
  345. end
  346. def mask!(mask)
  347. if mask.kind_of?(String)
  348. if mask =~ /^\d+$/
  349. prefixlen = mask.to_i
  350. else
  351. m = IPAddr.new(mask)
  352. if m.family != @family
  353. raise ArgumentError, "address family is not same"
  354. end
  355. @mask_addr = m.to_i
  356. @addr &= @mask_addr
  357. return self
  358. end
  359. else
  360. prefixlen = mask
  361. end
  362. case @family
  363. when Socket::AF_INET
  364. if prefixlen < 0 || prefixlen > 32
  365. raise ArgumentError, "invalid length"
  366. end
  367. masklen = 32 - prefixlen
  368. @mask_addr = ((IN4MASK >> masklen) << masklen)
  369. when Socket::AF_INET6
  370. if prefixlen < 0 || prefixlen > 128
  371. raise ArgumentError, "invalid length"
  372. end
  373. masklen = 128 - prefixlen
  374. @mask_addr = ((IN6MASK >> masklen) << masklen)
  375. else
  376. raise "unsupported address family"
  377. end
  378. @addr = ((@addr >> masklen) << masklen)
  379. return self
  380. end
  381. private
  382. # Creates a new ipaddr object either from a human readable IP
  383. # address representation in string, or from a packed in_addr value
  384. # followed by an address family.
  385. #
  386. # In the former case, the following are the valid formats that will
  387. # be recognized: "address", "address/prefixlen" and "address/mask",
  388. # where IPv6 address may be enclosed in square brackets (`[' and
  389. # `]'). If a prefixlen or a mask is specified, it returns a masked
  390. # IP address. Although the address family is determined
  391. # automatically from a specified string, you can specify one
  392. # explicitly by the optional second argument.
  393. #
  394. # Otherwise an IP address is generated from a packed in_addr value
  395. # and an address family.
  396. #
  397. # The IPAddr class defines many methods and operators, and some of
  398. # those, such as &, |, include? and ==, accept a string, or a packed
  399. # in_addr value instead of an IPAddr object.
  400. def initialize(addr = '::', family = Socket::AF_UNSPEC)
  401. if !addr.kind_of?(String)
  402. case family
  403. when Socket::AF_INET, Socket::AF_INET6
  404. set(addr.to_i, family)
  405. @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK
  406. return
  407. when Socket::AF_UNSPEC
  408. raise ArgumentError, "address family must be specified"
  409. else
  410. raise ArgumentError, "unsupported address family: #{family}"
  411. end
  412. end
  413. prefix, prefixlen = addr.split('/')
  414. if prefix =~ /^\[(.*)\]$/i
  415. prefix = $1
  416. family = Socket::AF_INET6
  417. end
  418. # It seems AI_NUMERICHOST doesn't do the job.
  419. #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
  420. # Socket::AI_NUMERICHOST)
  421. begin
  422. IPSocket.getaddress(prefix) # test if address is valid
  423. rescue
  424. raise ArgumentError, "invalid address"
  425. end
  426. @addr = @family = nil
  427. if family == Socket::AF_UNSPEC || family == Socket::AF_INET
  428. @addr = in_addr(prefix)
  429. if @addr
  430. @family = Socket::AF_INET
  431. end
  432. end
  433. if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6)
  434. @addr = in6_addr(prefix)
  435. @family = Socket::AF_INET6
  436. end
  437. if family != Socket::AF_UNSPEC && @family != family
  438. raise ArgumentError, "address family mismatch"
  439. end
  440. if prefixlen
  441. mask!(prefixlen)
  442. else
  443. @mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK
  444. end
  445. end
  446. def coerce_other(other)
  447. case other
  448. when IPAddr
  449. other
  450. when String
  451. self.class.new(other)
  452. else
  453. self.class.new(other, @family)
  454. end
  455. end
  456. def in_addr(addr)
  457. if addr =~ /^\d+\.\d+\.\d+\.\d+$/
  458. return addr.split('.').inject(0) { |i, s|
  459. i << 8 | s.to_i
  460. }
  461. end
  462. return nil
  463. end
  464. def in6_addr(left)
  465. case left
  466. when /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i
  467. return in_addr($1) + 0xffff00000000
  468. when /^::(\d+\.\d+\.\d+\.\d+)$/i
  469. return in_addr($1)
  470. when /[^0-9a-f:]/i
  471. raise ArgumentError, "invalid address"
  472. when /^(.*)::(.*)$/
  473. left, right = $1, $2
  474. else
  475. right = ''
  476. end
  477. l = left.split(':')
  478. r = right.split(':')
  479. rest = 8 - l.size - r.size
  480. if rest < 0
  481. return nil
  482. end
  483. return (l + Array.new(rest, '0') + r).inject(0) { |i, s|
  484. i << 16 | s.hex
  485. }
  486. end
  487. def addr_mask(addr)
  488. case @family
  489. when Socket::AF_INET
  490. return addr & IN4MASK
  491. when Socket::AF_INET6
  492. return addr & IN6MASK
  493. else
  494. raise "unsupported address family"
  495. end
  496. end
  497. def _reverse
  498. case @family
  499. when Socket::AF_INET
  500. return (0..3).map { |i|
  501. (@addr >> (8 * i)) & 0xff
  502. }.join('.')
  503. when Socket::AF_INET6
  504. return ("%.32x" % @addr).reverse!.gsub!(/.(?!$)/, '\&.')
  505. else
  506. raise "unsupported address family"
  507. end
  508. end
  509. def _to_string(addr)
  510. case @family
  511. when Socket::AF_INET
  512. return (0..3).map { |i|
  513. (addr >> (24 - 8 * i)) & 0xff
  514. }.join('.')
  515. when Socket::AF_INET6
  516. return (("%.32x" % addr).gsub!(/.{4}(?!$)/, '\&:'))
  517. else
  518. raise "unsupported address family"
  519. end
  520. end
  521. end
  522. if $0 == __FILE__
  523. eval DATA.read, nil, $0, __LINE__+4
  524. end
  525. __END__
  526. require 'test/unit'
  527. class TC_IPAddr < Test::Unit::TestCase
  528. def test_s_new
  529. assert_nothing_raised {
  530. IPAddr.new("3FFE:505:ffff::/48")
  531. IPAddr.new("0:0:0:1::")
  532. IPAddr.new("2001:200:300::/48")
  533. }
  534. a = IPAddr.new
  535. assert_equal("::", a.to_s)
  536. assert_equal("0000:0000:0000:0000:0000:0000:0000:0000", a.to_string)
  537. assert_equal(Socket::AF_INET6, a.family)
  538. a = IPAddr.new("0123:4567:89ab:cdef:0ABC:DEF0:1234:5678")
  539. assert_equal("123:4567:89ab:cdef:abc:def0:1234:5678", a.to_s)
  540. assert_equal("0123:4567:89ab:cdef:0abc:def0:1234:5678", a.to_string)
  541. assert_equal(Socket::AF_INET6, a.family)
  542. a = IPAddr.new("3ffe:505:2::/48")
  543. assert_equal("3ffe:505:2::", a.to_s)
  544. assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
  545. assert_equal(Socket::AF_INET6, a.family)
  546. assert_equal(false, a.ipv4?)
  547. assert_equal(true, a.ipv6?)
  548. assert_equal("#<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>", a.inspect)
  549. a = IPAddr.new("3ffe:505:2::/ffff:ffff:ffff::")
  550. assert_equal("3ffe:505:2::", a.to_s)
  551. assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
  552. assert_equal(Socket::AF_INET6, a.family)
  553. a = IPAddr.new("0.0.0.0")
  554. assert_equal("0.0.0.0", a.to_s)
  555. assert_equal("0.0.0.0", a.to_string)
  556. assert_equal(Socket::AF_INET, a.family)
  557. a = IPAddr.new("192.168.1.2")
  558. assert_equal("192.168.1.2", a.to_s)
  559. assert_equal("192.168.1.2", a.to_string)
  560. assert_equal(Socket::AF_INET, a.family)
  561. assert_equal(true, a.ipv4?)
  562. assert_equal(false, a.ipv6?)
  563. a = IPAddr.new("192.168.1.2/24")
  564. assert_equal("192.168.1.0", a.to_s)
  565. assert_equal("192.168.1.0", a.to_string)
  566. assert_equal(Socket::AF_INET, a.family)
  567. assert_equal("#<IPAddr: IPv4:192.168.1.0/255.255.255.0>", a.inspect)
  568. a = IPAddr.new("192.168.1.2/255.255.255.0")
  569. assert_equal("192.168.1.0", a.to_s)
  570. assert_equal("192.168.1.0", a.to_string)
  571. assert_equal(Socket::AF_INET, a.family)
  572. assert_equal("0:0:0:1::", IPAddr.new("0:0:0:1::").to_s)
  573. assert_equal("2001:200:300::", IPAddr.new("2001:200:300::/48").to_s)
  574. assert_equal("2001:200:300::", IPAddr.new("[2001:200:300::]/48").to_s)
  575. [
  576. ["fe80::1%fxp0"],
  577. ["::1/255.255.255.0"],
  578. ["::1:192.168.1.2/120"],
  579. [IPAddr.new("::1").to_i],
  580. ["::ffff:192.168.1.2/120", Socket::AF_INET],
  581. ["[192.168.1.2]/120"],
  582. ].each { |args|
  583. assert_raises(ArgumentError) {
  584. IPAddr.new(*args)
  585. }
  586. }
  587. end
  588. def test_s_new_ntoh
  589. addr = ''
  590. IPAddr.new("1234:5678:9abc:def0:1234:5678:9abc:def0").hton.each_byte { |c|
  591. addr += sprintf("%02x", c)
  592. }
  593. assert_equal("123456789abcdef0123456789abcdef0", addr)
  594. addr = ''
  595. IPAddr.new("123.45.67.89").hton.each_byte { |c|
  596. addr += sprintf("%02x", c)
  597. }
  598. assert_equal(sprintf("%02x%02x%02x%02x", 123, 45, 67, 89), addr)
  599. a = IPAddr.new("3ffe:505:2::")
  600. assert_equal("3ffe:505:2::", IPAddr.new_ntoh(a.hton).to_s)
  601. a = IPAddr.new("192.168.2.1")
  602. assert_equal("192.168.2.1", IPAddr.new_ntoh(a.hton).to_s)
  603. end
  604. def test_ipv4_compat
  605. a = IPAddr.new("::192.168.1.2")
  606. assert_equal("::192.168.1.2", a.to_s)
  607. assert_equal("0000:0000:0000:0000:0000:0000:c0a8:0102", a.to_string)
  608. assert_equal(Socket::AF_INET6, a.family)
  609. assert_equal(true, a.ipv4_compat?)
  610. b = a.native
  611. assert_equal("192.168.1.2", b.to_s)
  612. assert_equal(Socket::AF_INET, b.family)
  613. assert_equal(false, b.ipv4_compat?)
  614. a = IPAddr.new("192.168.1.2")
  615. b = a.ipv4_compat
  616. assert_equal("::192.168.1.2", b.to_s)
  617. assert_equal(Socket::AF_INET6, b.family)
  618. end
  619. def test_ipv4_mapped
  620. a = IPAddr.new("::ffff:192.168.1.2")
  621. assert_equal("::ffff:192.168.1.2", a.to_s)
  622. assert_equal("0000:0000:0000:0000:0000:ffff:c0a8:0102", a.to_string)
  623. assert_equal(Socket::AF_INET6, a.family)
  624. assert_equal(true, a.ipv4_mapped?)
  625. b = a.native
  626. assert_equal("192.168.1.2", b.to_s)
  627. assert_equal(Socket::AF_INET, b.family)
  628. assert_equal(false, b.ipv4_mapped?)
  629. a = IPAddr.new("192.168.1.2")
  630. b = a.ipv4_mapped
  631. assert_equal("::ffff:192.168.1.2", b.to_s)
  632. assert_equal(Socket::AF_INET6, b.family)
  633. end
  634. def test_reverse
  635. assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa", IPAddr.new("3ffe:505:2::f").reverse)
  636. assert_equal("1.2.168.192.in-addr.arpa", IPAddr.new("192.168.2.1").reverse)
  637. end
  638. def test_ip6_arpa
  639. assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa", IPAddr.new("3ffe:505:2::f").ip6_arpa)
  640. assert_raises(ArgumentError) {
  641. IPAddr.new("192.168.2.1").ip6_arpa
  642. }
  643. end
  644. def test_ip6_int
  645. assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.int", IPAddr.new("3ffe:505:2::f").ip6_int)
  646. assert_raises(ArgumentError) {
  647. IPAddr.new("192.168.2.1").ip6_int
  648. }
  649. end
  650. def test_to_s
  651. assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0001", IPAddr.new("3ffe:505:2::1").to_string)
  652. assert_equal("3ffe:505:2::1", IPAddr.new("3ffe:505:2::1").to_s)
  653. end
  654. end
  655. class TC_Operator < Test::Unit::TestCase
  656. IN6MASK32 = "ffff:ffff::"
  657. IN6MASK128 = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
  658. def setup
  659. @in6_addr_any = IPAddr.new()
  660. @a = IPAddr.new("3ffe:505:2::/48")
  661. @b = IPAddr.new("0:0:0:1::")
  662. @c = IPAddr.new(IN6MASK32)
  663. end
  664. alias set_up setup
  665. def test_or
  666. assert_equal("3ffe:505:2:1::", (@a | @b).to_s)
  667. a = @a
  668. a |= @b
  669. assert_equal("3ffe:505:2:1::", a.to_s)
  670. assert_equal("3ffe:505:2::", @a.to_s)
  671. assert_equal("3ffe:505:2:1::",
  672. (@a | 0x00000000000000010000000000000000).to_s)
  673. end
  674. def test_and
  675. assert_equal("3ffe:505::", (@a & @c).to_s)
  676. a = @a
  677. a &= @c
  678. assert_equal("3ffe:505::", a.to_s)
  679. assert_equal("3ffe:505:2::", @a.to_s)
  680. assert_equal("3ffe:505::", (@a & 0xffffffff000000000000000000000000).to_s)
  681. end
  682. def test_shift_right
  683. assert_equal("0:3ffe:505:2::", (@a >> 16).to_s)
  684. a = @a
  685. a >>= 16
  686. assert_equal("0:3ffe:505:2::", a.to_s)
  687. assert_equal("3ffe:505:2::", @a.to_s)
  688. end
  689. def test_shift_left
  690. assert_equal("505:2::", (@a << 16).to_s)
  691. a = @a
  692. a <<= 16
  693. assert_equal("505:2::", a.to_s)
  694. assert_equal("3ffe:505:2::", @a.to_s)
  695. end
  696. def test_carrot
  697. a = ~@in6_addr_any
  698. assert_equal(IN6MASK128, a.to_s)
  699. assert_equal("::", @in6_addr_any.to_s)
  700. end
  701. def test_equal
  702. assert_equal(true, @a == IPAddr.new("3ffe:505:2::"))
  703. assert_equal(false, @a == IPAddr.new("3ffe:505:3::"))
  704. assert_equal(true, @a != IPAddr.new("3ffe:505:3::"))
  705. assert_equal(false, @a != IPAddr.new("3ffe:505:2::"))
  706. end
  707. def test_mask
  708. a = @a.mask(32)
  709. assert_equal("3ffe:505::", a.to_s)
  710. assert_equal("3ffe:505:2::", @a.to_s)
  711. end
  712. def test_include?
  713. assert_equal(true, @a.include?(IPAddr.new("3ffe:505:2::")))
  714. assert_equal(true, @a.include?(IPAddr.new("3ffe:505:2::1")))
  715. assert_equal(false, @a.include?(IPAddr.new("3ffe:505:3::")))
  716. net1 = IPAddr.new("192.168.2.0/24")
  717. assert_equal(true, net1.include?(IPAddr.new("192.168.2.0")))
  718. assert_equal(true, net1.include?(IPAddr.new("192.168.2.255")))
  719. assert_equal(false, net1.include?(IPAddr.new("192.168.3.0")))
  720. # test with integer parameter
  721. int = (192 << 24) + (168 << 16) + (2 << 8) + 13
  722. assert_equal(true, net1.include?(int))
  723. assert_equal(false, net1.include?(int+255))
  724. end
  725. def test_hash
  726. a1 = IPAddr.new('192.168.2.0')
  727. a2 = IPAddr.new('192.168.2.0')
  728. a3 = IPAddr.new('3ffe:505:2::1')
  729. a4 = IPAddr.new('3ffe:505:2::1')
  730. a5 = IPAddr.new('127.0.0.1')
  731. a6 = IPAddr.new('::1')
  732. a7 = IPAddr.new('192.168.2.0/25')
  733. a8 = IPAddr.new('192.168.2.0/25')
  734. h = { a1 => 'ipv4', a2 => 'ipv4', a3 => 'ipv6', a4 => 'ipv6', a5 => 'ipv4', a6 => 'ipv6', a7 => 'ipv4', a8 => 'ipv4'}
  735. assert_equal(5, h.size)
  736. assert_equal('ipv4', h[a1])
  737. assert_equal('ipv4', h[a2])
  738. assert_equal('ipv6', h[a3])
  739. assert_equal('ipv6', h[a4])
  740. require 'set'
  741. s = Set[a1, a2, a3, a4, a5, a6, a7, a8]
  742. assert_equal(5, s.size)
  743. assert_equal(true, s.include?(a1))
  744. assert_equal(true, s.include?(a2))
  745. assert_equal(true, s.include?(a3))
  746. assert_equal(true, s.include?(a4))
  747. assert_equal(true, s.include?(a5))
  748. assert_equal(true, s.include?(a6))
  749. end
  750. end