php - 从 CIDR 前缀计算 IPv6 范围?

标签 php ipv6 cidr

我可以使用来自各种在线资源的代码片段对 IPv4 执行此操作。我想知道是否有办法使用 IPv6 来做到这一点。

基本上我只需要一个可以输入 IPv6 地址和前缀(例如:f080:42d2:581a::0/68)的表格,它会计算网络地址、第一个可用地址、最后一个可用地址和广播地址.然后只打印到屏幕。不打算将其存储在数据库或其他任何东西中。

最佳答案

首先:IPv6 没有网络地址和广播地址。您可以在前缀中使用所有地址。第二:在 LAN 上,前缀长度总是(好吧,99.x% 的时间)a/64。路由/68 会破坏无状态自动配置等 IPv6 功能。

下面是 IPv6 前缀计算器的详细实现:

<?php

/*
 * This is definitely not the fastest way to do it!
 */

// An example prefix
$prefix = '2001:db8:abc:1400::/54';

// Split in address and prefix length
list($firstaddrstr, $prefixlen) = explode('/', $prefix);

// Parse the address into a binary string
$firstaddrbin = inet_pton($firstaddrstr);

// Convert the binary string to a string with hexadecimal characters
# unpack() can be replaced with bin2hex()
# unpack() is used for symmetry with pack() below
$firstaddrhex = reset(unpack('H*', $firstaddrbin));

// Overwriting first address string to make sure notation is optimal
$firstaddrstr = inet_ntop($firstaddrbin);

// Calculate the number of 'flexible' bits
$flexbits = 128 - $prefixlen;

// Build the hexadecimal string of the last address
$lastaddrhex = $firstaddrhex;

// We start at the end of the string (which is always 32 characters long)
$pos = 31;
while ($flexbits > 0) {
  // Get the character at this position
  $orig = substr($lastaddrhex, $pos, 1);

  // Convert it to an integer
  $origval = hexdec($orig);

  // OR it with (2^flexbits)-1, with flexbits limited to 4 at a time
  $newval = $origval | (pow(2, min(4, $flexbits)) - 1);

  // Convert it back to a hexadecimal character
  $new = dechex($newval);

  // And put that character back in the string
  $lastaddrhex = substr_replace($lastaddrhex, $new, $pos, 1);

  // We processed one nibble, move to previous position
  $flexbits -= 4;
  $pos -= 1;
}

// Convert the hexadecimal string to a binary string
# Using pack() here
# Newer PHP version can use hex2bin()
$lastaddrbin = pack('H*', $lastaddrhex);

// And create an IPv6 address from the binary string
$lastaddrstr = inet_ntop($lastaddrbin);

// Report to user
echo "Prefix: $prefix\n";
echo "First: $firstaddrstr\n";
echo "Last: $lastaddrstr\n";

?>

它应该输出:

Prefix: 2001:db8:abc:1400::/54
First: 2001:db8:abc:1400::
Last: 2001:db8:abc:17ff:ffff:ffff:ffff:ffff

关于php - 从 CIDR 前缀计算 IPv6 范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10085266/

相关文章:

php - 如何使名称变量可点击(mysqli)?

python - 检查IP地址版本的最快方法

java - Tomcat 中的 HttpServletRequest.getRemoteAddr() 返回 IPv6 格式的 IP 地址

azure - azure功能支持ipv6吗?

amazon-ec2 - IPv6 地址到 CIDR block

java - 从 CIDR 表示法到 IP 地址/子网掩码(点十进制)的转换

Cidr 阻止 AWS 解释

php - 从数据库读取值后显示选中和未选中的复选框列表不起作用

php - 让 WebSocket 从远程 URL 工作

php - API 安全 - 使用 api key secret 、散列、tnonce 等 VS。 SSL证书验证