【发布时间】:2012-01-14 07:37:09
【问题描述】:
在我的项目中,我在 postgres (plpgsql) 中有一个函数,可以根据给定的 IP 地址确定国家/地区:
CREATE OR REPLACE FUNCTION get_country_for_ip(character varying)
RETURNS character varying AS
$BODY$
declare
ip ALIAS for $1;
ccode varchar;
cparts varchar[];
nparts bigint[];
addr bigint;
begin
cparts := string_to_array(ip, '.');
if array_upper(cparts, 1) <> 4 then
raise exception 'gcfi01: Invalid IP address: %', ip;
end if;
nparts := array[a2i(cparts[1])::bigint, a2i(cparts[2])::bigint, a2i(cparts[3])::bigint, a2i(cparts[4])::bigint];
if(nparts[1] is null or nparts[1] < 0 or nparts[1] > 255 or
nparts[2] is null or nparts[2] < 0 or nparts[2] > 255 or
nparts[3] is null or nparts[3] < 0 or nparts[3] > 255 or
nparts[4] is null or nparts[4] < 0 or nparts[4] > 255) then
raise exception 'gcfi02: Invalid IP address: %', ip;
end if;
addr := (nparts[1] << 24) | (nparts[2] << 16) | (nparts[3] << 8) | nparts[4];
addr := nparts[1] * 256 * 65536 + nparts[2] * 65536 + nparts[3] * 256 + nparts[4];
select into ccode t_country_code from ip_to_country where addr between n_from and n_to limit 1;
if ccode is null then
ccode := '';
end if;
return ccode;
end;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
这可能不是最有效的,但它可以完成工作。请注意,它使用了一个内部表 (ip_to_country),其中包含以下数据(数字 n_from 和 n_to 是地址范围的开始和结束的long 值:
n_from | n_to | t_country_code
----------+----------+----------------
0 | 16777215 | ZZ
16777216 | 16777471 | AU
...
现在我们也开始研究 IPv6 寻址 - 我需要为 IPv6 地址添加类似的功能。我有一组类似的 IPv6 数据,如下所示:
t_start | t_end | t_country_code
-------------+-----------------------------------------+----------------
:: | ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | ZZ
100:: | 1ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | ZZ
...
2000:: | 2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff | ZZ
...
2001:1200:: | 2001:1200:ffff:ffff:ffff:ffff:ffff:ffff | MX
...
现在,给定一个 IP 地址 ::1,我如何 (1) 检查它是否是有效的 IPv6 地址并 (2) 获取相应的国家/地区映射?
【问题讨论】:
-
您确定 IPv6 将以与 IPv4 类似的方式映射吗?有足够的 IPv6 地址供地球上的所有人口使用,还有一些。如果重新使用 IP 地址,您的映射技术似乎将无效。你的数据源是什么?有一些正则表达式可以帮助您验证 IPv6 是否有效。
-
@Ramhound:我们正在使用来自 Webnet77 (webnet77.com) 的信息,它为我们提供了很好的 IPv4 服务,因此我们从他们的 IPv6 数据库开始。我不太担心 100% 的时间是否正确(目前),但需要从某个地方开始。
标签: validation postgresql ip-address ipv6