如何从IP计算网络?

时间:2017-02-06 18:27:16

标签: sql sql-server

我有以下IP地址(示例):195.65.254.11

我希望构建一组查询(或函数)来返回此IP所属的网络(195.65.254.0/24

我首先将IP转换为整数:

create function [dbo].[IPAddressToInteger] (@IP as varchar(15))
returns bigint
as
begin
 return (convert(bigint, parsename(@IP,1)) +
         convert(bigint, parsename(@IP,2)) * 256 +
         convert(bigint, parsename(@IP,3)) * 256 * 256 +
         convert(bigint, parsename(@IP,4)) * 256 * 256 * 256)
end

select dbo.IPAddressToInteger('195.65.254.11'); -- 3275881995

然后我计算了CIDR:

create function [dbo].[CIDRFromMask] (@mask as bigint)
returns varchar(5)
as
begin
     declare @maskCalc bigint
     select  @maskCalc = dbo.IPAddressToInteger('255.255.255.255') - @mask + 1

     declare @logCalc int
     select  @logCalc = (32 - log(@maskCalc, 2))

     return '/' + cast(@logCalc as varchar(5))
end

select dbo.CIDRFromMask('3275881995'); -- /2

但在这里我被困住了。如何继续检索正确的网络

1 个答案:

答案 0 :(得分:0)

如果您有网络表,请将开始和停止范围存储为列。例如:

Network      Start      Stop        Name
1.0.0.0/24   1.0.0.0    1.0.0.255   Some guy

(实际上,StartStop将存储为整数,但对于此示例,我显示的是点分四维)

要查询地址所属的网络,请使用BETWEEN

SELECT n.Network, n.Name
FROM Networks n
WHERE @TargetAddress BETWEEN n.Start and n.Stop

(同样,根据需要插入IPAddressToInteger的调用)

要从网络地址和掩码生成StartStop值,请使用以下公式。

Start = Network Address
Stop  = Network Address | (~Subnet Mask)

在假设没有全局可路由网络将使用长度超过64位的前缀(我认为是这种情况,但我目前懒得验证)的情况下,使用64位整数可以在这种设计中简单地容纳IPv6。 / p>

BETWEENStartStop一起使用的优势在于查询能够利用您创建的索引,与使用{{1 }}

相关问题