SQLを使用してサブネットマスクのcidr値を決定する
質問
データベースに保存されているサブネットマスクのcidr(ビット表現)を計算するSQLクエリを実行する方法を見つけたいです。たとえば、データベースに255.255.255.0またはその10進数値(4294967040)が格納されています。クエリを使用して、選択して/ 24表現を取得します。
サブネットの最後のIPを決定するために次のようなことをしたので、マスクのcidr表現を決定するために同様のことをしたいと思っています。
select concat(inet_ntoa(ip_addr),'-',
inet_ntoa(ip_addr+(POWER(2,32)-ip_mask-1))) range
from subnets
order by ip_addr
できれば、これはmysql、postgres、oracleなどで機能するSQLステートメントです。
解決
自分の問題の解決策を見つけたと思います。これが私がやったことです:
select CONCAT(INET_NTOA(ip_addr),'/',32-log2((4294967296-ip_mask))) net
from subnets
order by ip_addr
基本的に、デクマールマスクを取得し、最大10進数値から減算します。次に、その値のlog2を使用して、対数値を取得します。次に、32(使用可能な最大ビット)から単純に減算します。
他の人を助ける希望。
ありがとう
他のヒント
SQLクエリには手続き型のループ構造はありません(手続き型言語にもかかわらず)が、ある行のセットを別の行のセットと比較できます。これはループのようなものです。
可能なサブネットマスクは32個のみです。このような場合、これらの32個のマスクと関連するCIDR番号を格納する小さなテーブルを作成するのが理にかなっています。
CREATE TABLE cidr (
bits INT UNSIGNED PRIMARY KEY,
mask INT UNSIGNED NOT NULL
);
INSERT INTO cidr (bits) VALUES
( 1), ( 2), ( 3), ( 4), ( 5), ( 6), ( 7), ( 8), ( 9), (10),
(11), (12), (13), (14), (15), (16), (17), (18), (19), (20),
(21), (22), (23), (24), (25), (26), (27), (28), (29), (30),
(31), (32);
UPDATE cidr SET mask = ((POWER(2,32)-1)<<(32-bits)) & (POWER(2,32)-1);
SELECT CONCAT(s.ip_addr, '/', c.bits)
FROM cidr c JOIN subnets s ON (c.mask = inet_aton(s.ip_mask));
e.g。 255.255.255.252
ネットマスクをビットマスクに変換する必要があります。
常にこの単純なクエリを使用します(PostgreSQL):
SELECT 32-length(trim(((split_part('255.255.255.252','.',1)::bigint*(256^3)::bigint +
split_part('255.255.255.252','.',2)::bigint*(256^2)::bigint +
split_part('255.255.255.252','.',3)::bigint*256 +
split_part('255.255.255.252','.',4)::bigint)::bit(32))::text,'1'));
あまり良いものではありませんが、短くて魅力的です。
--
-- Dumping routines for database
--
/*!50003 DROP FUNCTION IF EXISTS `INET_ATOC` */;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ALLOW_INVALID_DATES' */ ;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` FUNCTION `INET_ATOC`(`paramNETMASK` varchar(15)) RETURNS int(2) unsigned
DETERMINISTIC
COMMENT 'Converts an IPv4 netmask in dotted decimal notation to a CIDR integer between 0 and 32'
BEGIN
DECLARE `netmask` int unsigned;
DECLARE `cidr` int unsigned;
SET `netmask` = INET_ATON(`paramNETMASK`);
IF (`netmask` IS NULL)
THEN
RETURN NULL;
ELSE
SET `cidr` = 0;
countNetBits: WHILE (`cidr` < 32)
DO
IF ( (0x80000000 & `netmask`) = 0x80000000 )
THEN
SET `netmask` = 0xFFFFFFFF & (`netmask` << 1);
SET `cidr` = `cidr` + 1;
ELSE
LEAVE countNetBits;
END IF;
END WHILE;
IF (`netmask` != 0)
THEN
RETURN NULL;
END IF;
RETURN `cidr`;
END IF;
END ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 DROP FUNCTION IF EXISTS `INET_CTOA` */;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ALLOW_INVALID_DATES' */ ;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` FUNCTION `INET_CTOA`(`paramCIDR` int) RETURNS varchar(15) CHARSET utf8
DETERMINISTIC
COMMENT 'Converts a CIDR suffix (integer between 0 and 32) to an IPv4 netmask in dotted decimal notation'
BEGIN
DECLARE `netmask` int unsigned;
IF ( (`paramCIDR` < 0) OR (`paramCIDR` > 32) )
THEN
RETURN NULL;
ELSE
SET `netmask` = 0xFFFFFFFF - (pow( 2, (32-`paramCIDR`) ) - 1);
RETURN INET_NTOA(`netmask`);
END IF;
END ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 DROP PROCEDURE IF EXISTS `getSubnet` */;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `getSubnet`(INOUT `paramADDR` VARCHAR(15), INOUT `paramCIDR` INT, OUT `paramMASK` VARCHAR(15), OUT `paramNETWORK` VARCHAR(15), OUT `paramBROADCAST` VARCHAR(15), OUT `paramNUMHOSTS` INT) CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE `numaddrs` int unsigned;
DECLARE `ipaddr` int unsigned;
DECLARE `netmask` int unsigned;
DECLARE `wildcard` int unsigned;
DECLARE `network` int unsigned;
DECLARE `broadcast` int unsigned;
DECLARE `numhosts` int unsigned;
SET `ipaddr` = INET_ATON(`paramADDR`);
IF (`ipaddr` IS NULL) OR (`paramCIDR` < 1) OR (`paramCIDR` > 30)
THEN
SELECT
NULL, NULL, NULL, NULL, NULL, NULL
INTO
`paramADDR`, `paramCIDR`, `paramMASK`, `paramNETWORK`, `paramBROADCAST`, `paramNUMHOSTS`;
ELSE
SET `numaddrs` = pow( 2, (32-`paramCIDR`) );
SET `numhosts` = `numaddrs` - 2;
SET `netmask` = 0xFFFFFFFF - (`numaddrs` - 1);
SET `wildcard` = 0xFFFFFFFF & (~`netmask`);
SET `network` = `ipaddr` & `netmask`;
SET `broadcast` = `ipaddr` | `wildcard`;
SELECT
INET_NTOA(`ipaddr`), `paramCIDR`, INET_NTOA(`netmask`), INET_NTOA(`network`), INET_NTOA(`broadcast`), `numhosts`
INTO
`paramADDR`, `paramCIDR`, `paramMASK`, `paramNETWORK`, `paramBROADCAST`, `paramNUMHOSTS`;
END IF;
END ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
所属していません StackOverflow