【问题标题】:Converting mac address to IPv6 link local address in Ruby在Ruby中将mac地址转换为IPv6链接本地地址
【发布时间】:2019-12-30 06:52:16
【问题描述】:

如何在 Ruby 中将00:16:3e:15:d3:a9 之类的 mac 地址转换为 IPv6 链接本地地址(修改后的 EUI-64,例如 fe80::216:3eff:fe15:d3a9)?

到目前为止,我有以下步骤:

mac = "00:16:3e:15:d3:a9"
mac.delete!(':')        # Delete colons
mac.insert(6, 'fffe')   # Insert ff:ee in the middle
mac = mac.scan(/.{4}/)  # Split into octets of 4

next step 将翻转第一个八位字节的第六位,我遇到了麻烦。

【问题讨论】:

  • 您遇到的问题是您正在尝试使用文本来做到这一点。 IP 地址和 MAC 地址都是二进制数。您可以简单地使用按位或将 MAC 地址的 U/L 位设置为二进制数。然后,您可以转换回文本。

标签: ruby ipv6


【解决方案1】:

这是您的主要问题:Ruby 是一种面向对象的语言。您可以通过操作丰富的结构化对象来创建程序,更准确地说,是通过让丰富的结构化对象自行操作来创建程序。

但是,您正在操纵Strings。当然,Strings 在 Ruby 中也是对象,但它们是表示 文本 的对象,而不是表示 IP 地址 或 EUI 的对象。

您应该至少将 IP 地址或 EUI 视为 数字,而不是文本,但实际上,您应该将它们视为丰富的结构化 IP 地址对象或 EUI 对象.

Ruby 实际上带有 a library for manipulating IP addresses 作为其 standard library 的一部分。

以下是将这些地址视为数字和/或对象的示例:

require 'ipaddr'

eui48 = '00-16-3E-15-D3-A9'
# eliminate all delimiters, note that only ':' is not enough; the standard is '-', but '.' is also sometimes used
eui48 = eui48.gsub(/[^0-9a-zA-Z]/, '')
# parse the EUI-48 as a number
eui48 = eui48.to_i(16)

# split the EUI-48 into the OUI and the manufacturer-assigned parts
oui, assigned = eui48.divmod(1 << 24)

# append 16 zero bits to the OUI
left = oui << 16
# add the standard bit sequence
left += 0xfffe
# append 24 zero bits
left <<= 24

# now we have an EUI-64
eui64 = left + assigned

# flip bit index 57 to create a modified EUI-64
modified_eui64 = eui64 ^ 1 << 57

# the prefix for link-local IPv6 addresses is fe80::/10, link-local addresses are in the fe80::/64 network
prefix = IPAddr.new('fe80::/64')

# the suffix is based on our modified EUI-64
suffix = IPAddr.new(modified_eui64, Socket::AF_INET6)

# the final result is the bitwise logical OR of the prefix and suffix
link_local_ipv6 = prefix | suffix

# the IP address library knows how to correctly format an address according to RFC 5952 Section 4
link_local_ipv6.to_s
#=> 'fe80::216:3eff:fe15:d3a9'

【讨论】:

  • 创建前缀时&lt;&lt; 112有什么意义?你怎么能在那里传递任意前缀?
  • 链接本地地址的前缀是0xfe80,它是16位长,所以你必须再追加112位才能得到128位。
  • 其实想想,前缀只有10位,所以100%正确应该是0x3fa &lt;&lt; 118
  • 看起来IPAddr.new('fe80::/10', Socket::AF_INET6) 也可以。
  • 谢谢。解决了。​​实际上,您甚至不需要指定地址族,它可以自动检测到。
猜你喜欢
  • 1970-01-01
  • 2016-04-18
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 2018-12-26
  • 1970-01-01
相关资源
最近更新 更多