PageRenderTime 58ms CodeModel.GetById 10ms RepoModel.GetById 2ms app.codeStats 0ms

/lib/racket/l3/misc.rb

https://github.com/bahoom/racket
Ruby | 159 lines | 91 code | 17 blank | 51 comment | 8 complexity | c42e7c6a5930761bef8e3fb752527ed4 MD5 | raw file
  1. # $Id: misc.rb 14 2008-03-02 05:42:30Z warchild $
  2. #
  3. # Copyright (c) 2008, Jon Hart
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are met:
  8. # * Redistributions of source code must retain the above copyright
  9. # notice, this list of conditions and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above copyright
  11. # notice, this list of conditions and the following disclaimer in the
  12. # documentation and/or other materials provided with the distribution.
  13. # * Neither the name of the <organization> nor the
  14. # names of its contributors may be used to endorse or promote products
  15. # derived from this software without specific prior written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
  18. # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. # DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
  21. # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #
  28. require 'ipaddr'
  29. module Racket
  30. module L3
  31. # Miscelaneous L3 helper methods
  32. module Misc
  33. # given an IPv4 address packed as an integer
  34. # return the friendly "dotted quad"
  35. def Misc.long2ipv4(long)
  36. quad = Array.new(4)
  37. quad[0] = (long >> 24) & 255
  38. quad[1] = (long >> 16) & 255
  39. quad[2] = (long >> 8 ) & 255
  40. quad[3] = long & 255
  41. quad.join(".")
  42. end
  43. def Misc.randomipv4
  44. Misc.long2ipv4(rand(2**32))
  45. end
  46. # Compute link local address for a given mac address
  47. # From Daniele Bellucci
  48. def Misc.linklocaladdr(mac)
  49. mac = mac.split(":")
  50. mac[0] = (mac[0].to_i(16) ^ (1 << 1)).to_s(16)
  51. ["fe80", "", mac[0,2].join, mac[2,2].join("ff:fe"), mac[4,2].join].join(":")
  52. end
  53. # Given a long, convert it to an IPv6 address,
  54. # optionally compressing the address returned
  55. def Misc.long2ipv6(long, compress=true)
  56. ipv6 = []
  57. ipv6[0] = long >> 112
  58. ipv6[1] = (long >> 96) & (0xFFFF)
  59. ipv6[2] = (long >> 80) & (0xFFFF)
  60. ipv6[3] = (long >> 64) & (0xFFFF)
  61. ipv6[4] = (long >> 48) & (0xFFFF)
  62. ipv6[5] = (long >> 32) & (0xFFFF)
  63. ipv6[6] = (long >> 16) & (0xFFFF)
  64. ipv6[7] = long & (0xFFFF)
  65. ipv6 = ipv6.map { |o| o.to_s(16) }.join(":")
  66. compress ? Misc.compressipv6(ipv6) : ipv6
  67. end
  68. # Compress an IPv6 address
  69. # Inspired by Daniele Bellucci and jacked from ipaddr
  70. def Misc.compressipv6(ipv6)
  71. ipv6.gsub!(/\b0{1,3}([\da-f]+)\b/i, '\1')
  72. loop do
  73. break if ipv6.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
  74. break if ipv6.sub!(/\b0:0:0:0:0:0:0\b/, ':')
  75. break if ipv6.sub!(/\b0:0:0:0:0:0\b/, ':')
  76. break if ipv6.sub!(/\b0:0:0:0:0\b/, ':')
  77. break if ipv6.sub!(/\b0:0:0:0\b/, ':')
  78. break if ipv6.sub!(/\b0:0:0\b/, ':')
  79. break if ipv6.sub!(/\b0:0\b/, ':')
  80. break
  81. end
  82. ipv6.sub!(/:{3,}/, '::')
  83. if /\A::(ffff:)?([\da-f]{1,4}):([\da-f]{1,4})\Z/i =~ ipv6
  84. ipv6 = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256)
  85. end
  86. ipv6
  87. end
  88. def Misc.randomipv6
  89. Misc.long2ipv6(rand(2**128))
  90. end
  91. # given a string representing an IPv6
  92. # address, return the integer representation
  93. def Misc.ipv62long(ip)
  94. IPAddr.new(ip).to_i
  95. end
  96. # In addition to the regular multicast addresses, each unicast address
  97. # has a special multicast address called its solicited-node address. This
  98. # address is created through a special mapping from the device’s unicast
  99. # address. Solicited-node addresses are used by the IPv6 Neighbor
  100. # Discovery (ND) protocol to provide more efficient address resolution
  101. # than the ARP technique used in IPv4.
  102. # From Daniele Bellucci
  103. def Misc.soll_mcast_addr6(addr)
  104. h = addr.split(':')[-2, 2]
  105. m = []
  106. m << 'ff'
  107. m << (h[0].to_i(16) & 0xff).to_s(16)
  108. m << ((h[1].to_i(16) & (0xff << 8)) >> 8).to_s(16)
  109. m << (h[1].to_i(16) & 0xff).to_s(16)
  110. 'ff02::1:' + [m[0,2].join, m[2,2].join].join(':')
  111. end
  112. #
  113. def Misc.soll_mcast_mac(addr)
  114. h = addr.split(':')[-2, 2]
  115. m = []
  116. m << 'ff'
  117. m << (h[0].to_i(16) & 0xff).to_s(16)
  118. m << ((h[1].to_i(16) & (0xff << 8)) >> 8).to_s(16)
  119. m << (h[1].to_i(16) & 0xff).to_s(16)
  120. '33:33:' + m.join(':')
  121. end
  122. # given a "dotted quad" representing an IPv4
  123. # address, return the integer representation
  124. def Misc.ipv42long(ip)
  125. IPAddr.new(ip).to_i
  126. end
  127. # Calculate the checksum. 16 bit one's complement of the one's
  128. # complement sum of all 16 bit words
  129. def Misc.checksum(data)
  130. checksum = 0
  131. unpack = "S#{data.length / 2}#{data.length % 2 == 1 ? 'C' : ''}"
  132. data.unpack(unpack).each { |x|
  133. checksum += x
  134. }
  135. checksum = (checksum >> 16) + (checksum & 0xffff)
  136. checksum = ~((checksum >> 16) + checksum) & 0xffff
  137. ([checksum].pack("S*")).unpack("n*")[0]
  138. end
  139. end
  140. end
  141. end
  142. # vim: set ts=2 et sw=2: