PageRenderTime 26ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/vm-shared/ruby/2.0/ipaddr.rb

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