PHP5从cidr前缀计算IPv6范围?

Dam*_*man 5 php ipv6 prefix cidr

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

基本上我只需要一个表格,我可以输入一个IPv6地址和前缀(例如:地址/ 68),它可以计算网络地址,第一个可用地址,最后一个可用地址和广播地址.然后只需打印到屏幕.不希望将其存储在数据库或任何其他内容中.

我该怎么做呢?

感谢大家提前!

All*_*lis 7

这是对已接受答案的修复,该答案错误地假设“第一个地址”应与输入的字符串相同。相反,它需要通过AND运算符根据其掩码修改其值。

为了演示该问题,请考虑以下示例输入:2001:db8:abc:1403::/54

预期结果:

First: 2001:db8:abc:1400::
Run Code Online (Sandbox Code Playgroud)

实际结果:

First: 2001:db8:abc:1403::
Run Code Online (Sandbox Code Playgroud)

计算给定 4 位序列的掩码的相关数学是:

// Calculate the subnet mask. min() prevents the comparison from being negative
$mask = 0xf << (min(4, $flexbits));

// AND the original against its mask
$newval = $origval & $mask;
Run Code Online (Sandbox Code Playgroud)

完整代码

First: 2001:db8:abc:1400::
Run Code Online (Sandbox Code Playgroud)

输出:

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

Run Code Online (Sandbox Code Playgroud)


San*_*ann 6

首先:IPv6没有网络和广播地址.您可以使用前缀中的所有地址.第二:在局域网上,前缀长度总是(好,99.x%的时间)a/64.路由a/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";

?>
Run Code Online (Sandbox Code Playgroud)

它应该输出:

Prefix: 2001:db8:abc:1400::/54
First: 2001:db8:abc:1400::
Last: 2001:db8:abc:17ff:ffff:ffff:ffff:ffff
Run Code Online (Sandbox Code Playgroud)