如何在CIDR表示法中搜索IP地址

3

我需要在mysql数据库中搜索具有以下IP地址“192.168.0.1/20”的条目。

注意:存储的IP地址是变量(例如:192.168.0.3,192.168.0.4)

Address:   192.168.0.1          11000000.10101000.0000 0000.00000001
Netmask:   255.255.240.0 = 20   11111111.11111111.1111 0000.00000000
Wildcard:  0.0.15.255           00000000.00000000.0000 1111.11111111
=>
Network:   192.168.0.0/20       11000000.10101000.0000 0000.00000000
HostMin:   192.168.0.1          11000000.10101000.0000 0000.00000001
HostMax:   192.168.15.254       11000000.10101000.0000 1111.11111110
Broadcast: 192.168.15.255       11000000.10101000.0000 1111.11111111
Hosts/Net: 4094                  Class C, Private Internet

我的解决方案是根据给定的CIDR符号(用“*”替换0)找到网络地址,然后在数据库中搜索 192.168.*.* 条目,因为它们以字符串形式存储。这个方法可以运作,但我不确定是否正确。是否有人能指出问题或者比这更优化的解决方案?

1
你的解决方案使用 192.168.. 将无法生效,因为 192.168.0.1/20 的最大主机地址为 192.168.15.254,但是你的数据库中可能有像 192.168.16.1、192.168.16.2 等地址。 - Stanislav
啊哈,谢谢Stanislav(扶额) - forum.test17
就我而言,目前我只看到两种解决方案:获取所有地址并使用IN子句,或者取最小和最大主机,将它们分成4组,为每个组创建一个正则表达式(如果它们不相同),然后将4个正则表达式组合在一起,并尝试使用正则表达式调用查询。但这可能会导致选择不太优化... - Stanislav
这个怎么样:"SELECT * from addresses where INET_ATON(ip_address) > {STARTING_IP_ADDRESS} && INET_ATON(ip_address) < {EDING_IP_ADDRESS}; (https://www.ultratools.com/tools/netMaskResult?ipAddress=192.168.0.1%2F20+)" - forum.test17
让我们在聊天中继续这个讨论 - forum.test17
显示剩余2条评论
1个回答

1
以下内容仅适用于每个VARCHAR字段只有一个IP地址的情况。
正确的方法是使用INET_ATON()/INET_NTOA()函数根据子网掩码匹配IP地址所在的网络。
但需要进行多个步骤。首先使用以下代码将长度转换为子网掩码:
SET @l=20;
SELECT INET_NTOA(0xffffffff >> (32-@l) << (32-@l));

这只是为了传达这个想法,要使其更有用,您可以执行以下操作:

SELECT 0xffffffff >> (32-@l) << (32-@l) INTO @mask;


对于地址与网络地址的实际匹配,您可以使用带位运算符的INET_函数,例如:

SET @l=20;
SET @nw='192.168.0.0';
SELECT 0xffffffff >> (32-@l) << (32-@l) INTO @mask;
SELECT * FROM yourtable 
 WHERE (INET_ATON(addrfield) & @mask) = INET_ATON(@nw);

当然,您可以将其合并为一个语句,例如:
SELECT * FROM yourtable 
     WHERE (INET_ATON(addrfield) & (0xffffffff >> (32-@l) << (32-@l))) = INET_ATON('192.168.0.0');

你能否检查一下我的最后一条评论:“SELECT * from addresses where INET_ATON(ip_address) > {STARTING_IP_ADDRESS} && INET_ATON(ip_address) < {EDING_IP_ADDRESS}”,这样不就足够了吗? - forum.test17
1
@rockyit86,如果你有所述子网的网络地址和广播地址,那么这将有效。 - vhu
有趣的使用 LPAD()RPAD() 来构建掩码 @vhu。生成掩码的替代方法包括 0xffffffff >> @l << @l~0 >> 32 & ~0 << @l - Michael - sqlbot
@Michael-sqlbot,同意这是更好的方法。 - vhu
如果我做了减法就好了,唉。确实是(32 - @l)。+1 - Michael - sqlbot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接