使用MySQL检查同一子网中的两个IPv6地址

时间:2016-10-18 02:57:18

标签: mysql select ipv6 ipv4

我正在寻找一个select语句,它将检查2个IP地址是否在同一个子网中,具体取决于掩码主机部分中的位数。我找到this excellent question并回答,但它仅适用于IPv4地址。

我对IPv4的MySQL语句如下,其中3是掩码主机部分(21位网络)中的位数:

SELECT FROM table WHERE ((-1 << 3) & INET_ATON(IPADDRESS1) = (-1 << 3) & INET_ATON(IPADDRESS2))

任何人都可以创建IPv6等价物吗? (这甚至超出了我的努力)。我意识到有一个INET6_ATON,但我用来创建上面1的掩码的-1将无效(由于长度),以及可能的其他原因。

如果有帮助,我们可以假设IPv6地址是RFC 5952格式,或者是完整的8个冒号分隔数字。

2 个答案:

答案 0 :(得分:0)

这里有很多问题。大多数答案都是herereference implementation for IPv6

在你向我吐口水以获得仅限链接的答案之前,这里有一些关于发生了什么的提示。

  • 链接是指处理非重叠范围(如IP地址)的有效方法。但是,部分解决方案是能够从128位值中加/减1。请参阅函数IpIncrIpDecr

  • 为了制作面具,我建议转换为32个字符的十六进制,然后使用子串。请参阅CONCAT, LEFT, RIGHT, REPEAT等。完成此操作后,字符串比较应轻松处理网络&#34;中的&#34;。

MySQL 8.0中的代码会更简单,因为BLOBs可以被视为真正的长字符串;之前的比特限制为BIGINT,这对于IPv6来说还不够大。

答案 1 :(得分:0)

我有一个地址存储为字符串的解决方案。

类似的问题是找到数据库中属于特定子网的所有地址,这与此处发布的问题非常类似,以检查两个地址是否在同一子网中。

这有点棘手,特别是对于IPv6。在IPv6中,可以选择压缩段,例如1 :: 1,相当于1:0:0:0:0:0:0:1,这是它很棘手的主要原因。

The IPAddress Java library将生成mysql SQL以搜索给定子网中的地址。该链接更详细地描述了该问题。免责声明:我是项目经理。

基本算法是获取子网地址的网络部分,然后获取该部分的每个变体(例如,上面的两个字符串是完整地址1 :: 1的变体),然后计算段分隔符的数量,然后对匹配的地址执行mysql子字符串,还要计算匹配地址中的总分隔符。

以下是示例代码:

public static void main(String[] args) throws IPAddressStringException {
    System.out.println(getSearchSQL("columnX", "1.2.3.4/16"));
    System.out.println(getSearchSQL("columnX", "1:2:3:4:5:6:7:8/64"));
    System.out.println(getSearchSQL("columnX", "1::8/64"));
}

static String getSearchSQL(String expression, String ipAddressStr) throws IPAddressStringException {
    IPAddressString ipAddressString = new IPAddressString(ipAddressStr);
    IPAddress ipAddress = ipAddressString.toAddress();
    IPAddressSection networkPrefix = ipAddress.getNetworkSection(ipAddress.getNetworkPrefixLength(), false);
    StringBuilder sql = new StringBuilder("Select rows from table where ");
    networkPrefix.getStartsWithSQLClause(sql, expression);
    return sql.toString();
}

Ouptut:

Select rows from table where (substring_index(columnX,'.',2) = '1.2')
Select rows from table where (substring_index(columnX,':',4) = '1:2:3:4')
Select rows from table where ((substring_index(columnX,':',4) = '1:0:0:0') OR ((substring_index(columnX,':',2) = '1:') AND (LENGTH (columnX) - LENGTH(REPLACE(columnX, ':', '')) <= 5)))