我有一個MySQL黑名單表,其中包含單個IPv4,IPv6或其中一種類型的CIDR範圍。在CIDR範圍內找到IPv6的正確方法MySQL
我的表看起來有點這樣的:
+-----------+-------------+
| Name | Type |
+-----------+-------------+
| IpAddress | VARCHAR(46) |
+-----------+-------------+
| Mask | INT(2) |
+-----------+-------------+
現在,我想檢查一個給定的IP地址是否是在保存的CIDR的範圍之一。 我已經做到了這一點後,研究了一大堆的頁面了幾天,最後只移植了以下解決方案到MySQL:PHP5 calculate IPv6 range from cidr prefix?
所以我變換IP + CIDR掩碼的第一和最後一個IP在這個範圍內,然後我使用INET6_ATON將其轉換爲數字,並將其與BETWEEN運算符進行比較。
我的實現:
獲取最後一個IP
FUNCTION (`Ip` VARCHAR(46), `Mask` INT(2) UNSIGNED) RETURNS varchar(39)
BEGIN
DECLARE IpNumber VARBINARY(16);
DECLARE Last VARCHAR(39) DEFAULT '';
DECLARE FlexBits, Counter, Deci, NewByte INT UNSIGNED;
DECLARE HexIp VARCHAR(32);
SET IpNumber = INET6_ATON(Ip);
SET HexIp = HEX(IpNumber);
SET FlexBits = 128 - Mask;
SET Counter = 32;
WHILE (FlexBits > 0) DO
SET Deci = CONV(SUBSTR(HexIp, Counter, 1), 16, 10);
SET NewByte = Deci | (POW(2, LEAST(4, FlexBits)) - 1);
SET Last = CONCAT(CONV(NewByte, 10, 16), Last);
IF FlexBits >= 4 THEN SET FlexBits = FlexBits - 4;
ELSE SET FlexBits = 0;
END IF;
SET Counter = Counter - 1;
END WHILE;
SET Last = CONCAT(SUBSTR(HexIp, 1, Counter), Last);
RETURN INET6_NTOA(UNHEX(Last));
END
獲取第一個IP
FUNCTION (`Ip` VARCHAR(46), `Mask` INT(2) UNSIGNED, `WithMask` BOOLEAN) RETURNS varchar(39)
BEGIN
DECLARE First VARCHAR (42) DEFAULT '';
SET First = INET6_NTOA(UNHEX(RPAD(SUBSTR(HEX(INET6_ATON(Ip)), 1, Mask/4), 32, 0)));
IF (WithMask = 1) THEN
SET First = CONCAT(First, '/', CAST(Mask AS CHAR));
END IF;
RETURN First;
END
這工作得很好!我只是有一個想法,即使用一些聰明的位操作可以更高效地完成它。 我讀過很多關於這個主題的問題,但我沒有真正找到具體的解決方案 任何幫助正確的方向將非常感激!
注意:只有IPv6,我已經實現了IPv4的正確方式。
我知道這是非常古老的,但有MYSQL改變了它的功能嗎? 5.6根本不會接受這個。 –