【问题标题】:Get IP Address range from xxx.xxx.xx.0/16从 xxx.xxx.xx.0/16 获取 IP 地址范围
【发布时间】:2019-02-08 16:03:48
【问题描述】:

大家好,

有没有办法从 66.54.119.192/29 格式中获取 IP 地址范围

在 Oracle pl/sql 中类似于 66.54.119.192 - 66.54.119.198

感谢您提供的任何帮助。

【问题讨论】:

  • 向我们展示代码。你试过什么?应该可以的。
  • @MarkJ.Bobak 我尝试使用来自此 SO 线程 stackoverflow.com/questions/279431/… 的代码处理 INET_ATON 和 INET_NTOA 的黑客攻击。我没有成功获得范围。

标签: oracle


【解决方案1】:

没有直接的方法可以得到它。首先,您需要将 IP 拆分为 4 个八位字节,然后您必须从二进制 -> 十进制转换,反之亦然。

前段时间我为这样的任务创建了一个包。下面你只看到包体,它应该提供解决你问题的一切。

CREATE OR REPLACE TYPE NUMBER_TABLE_TYPE AS TABLE OF NUMBER;


CREATE OR REPLACE PACKAGE BODY IP_Utility AS

    BASE_BIN CONSTANT PLS_INTEGER := 2;
    BASE_OCT CONSTANT PLS_INTEGER := 8;
    BASE_DEC CONSTANT PLS_INTEGER := 10;
    BASE_HEX CONSTANT PLS_INTEGER := 16;

    NUMERIC_OVERFLOW EXCEPTION;
    PRAGMA EXCEPTION_INIT(NUMERIC_OVERFLOW, -1426);

/**
* Function translate a array to PL/SQL Table
* @param Sperator String that separates elements, e.g. ';'
* @return Table of elements (NUMBER)
*/
FUNCTION SplitNumber(LIST IN VARCHAR2, Separator IN VARCHAR2) RETURN NUMBER_TABLE_TYPE IS
    OutTable NUMBER_TABLE_TYPE; 
BEGIN    
    IF LIST IS NULL THEN
        RETURN NULL;
    ELSE
        SELECT TRIM(REGEXP_SUBSTR(LIST, '[^'||Separator||']+', 1, LEVEL)) 
        BULK COLLECT INTO OutTable
        FROM dual
        CONNECT BY REGEXP_SUBSTR(LIST, '[^'||Separator||']+', 1, LEVEL) IS NOT NULL;
    END IF;

    IF OutTable.COUNT > 0 THEN
        RETURN OutTable;
    ELSE
        RETURN NULL;
    END IF;     
END SplitNumber;



/**
* Convert a decimal nubmer into a binary/octal/hex string 
* @param DecN Integer decimal number
* @param Base The binary base (BASE_BIN, BASE_OCT, BASE_HEX)  
* @return The binary/octal/hex string
*/  
FUNCTION Dec2Base(DecN IN INTEGER, Base IN PLS_INTEGER DEFAULT BASE_HEX) RETURN VARCHAR2 DETERMINISTIC IS
    HexString CONSTANT CHAR(16) := '0123456789ABCDEF';
    DecNumber INTEGER := DecN;
    BaseString VARCHAR2(128) := NULL;
BEGIN
    IF DecN IS NULL THEN
        RETURN NULL;
    END IF;
    IF Base > 16 THEN 
        RAISE NUMERIC_OVERFLOW;
    END IF;
    LOOP
        BaseString := SUBSTR(HexString, MOD(DecNumber, Base) + 1, 1 ) || BaseString;
        DecNumber := TRUNC(DecNumber / Base);
        EXIT WHEN DecNumber = 0;
    END LOOP;
    RETURN BaseString;
END Dec2Base;


/**
* Convert a binary/octal/hex number into a decimal value 
* @param BaseString The binary/octal/hex string
* @param Base The binary base (BASE_BIN, BASE_OCT, BASE_HEX)  
* @return The decimal number    
*/
FUNCTION Base2Dec(BaseString IN VARCHAR2, Base IN PLS_INTEGER DEFAULT BASE_HEX) RETURN INTEGER DETERMINISTIC IS
    BaseNumber INTEGER := 0;
    HexString CONSTANT CHAR(16) := '0123456789ABCDEF';
BEGIN
    IF Base > 16 THEN 
        RAISE NUMERIC_OVERFLOW;
    END IF;
    IF BaseString IS NULL THEN
        RETURN NULL;
    END IF;
    FOR i IN 1..LENGTH(BaseString) LOOP
        BaseNumber := BaseNumber * Base + INSTR(HexString, UPPER(SUBSTR(BaseString, i, 1))) - 1;
    END LOOP;
    RETURN BaseNumber;
END Base2Dec;



/**
* Returns SubnetMask of given IP Address
* @param Ip IP-Address with CIDR, e.g. '10.152.10.17/27'
* @return SubnetMask The Subnet Mask in IPv4 Format, e.g. '255.255.255.224'
*/
FUNCTION GetSubnetMask(Ip IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS
    SubnetMask VARCHAR2(16);
    MaskBin VARCHAR2(32);
BEGIN
    IF Ip IS NULL OR NOT REGEXP_LIKE(Ip, '/\d+$') THEN
        RETURN NULL;
    END IF;
    FOR i IN 1..REGEXP_REPLACE(Ip, '.+/') LOOP
        MaskBin := MaskBin || '1';
    END LOOP;
    MaskBin := RPAD(MaskBin, 32, '0');
    FOR i IN 1..4 LOOP
        SubnetMask := SubnetMask ||'.'||Base2Dec(SUBSTR(MaskBin, 8*(i-1)+1, 8 ), BASE_BIN);
    END LOOP;
    SubnetMask := SUBSTR(SubnetMask, 2);
    RETURN SubnetMask;  
END GetSubnetMask;



/**
* Returns Subnet and Broadcast-IP of given IP Address  
* @param Ip IP-Address, e.g. 10.152.10.17
* @param SubnetMask The SubnetMask, e.g. 255.255.255.240  
* @param Subnet Subnet-IP: e.g. 10.152.10.16  
* @param BroadcastIp Broadcast-IP: e.g. 10.152.10.31
*/
PROCEDURE GetIpSubnet(Ip IN VARCHAR2, SubnetMask IN VARCHAR2, Subnet OUT VARCHAR2, BroadcastIp OUT VARCHAR2) IS
    SubnetBin VARCHAR2(8);
    BroadcastBin VARCHAR2(8);
    Ip_Array NUMBER_TABLE_TYPE;
    Mask_Array NUMBER_TABLE_TYPE;
BEGIN
    IF SubnetMask IS NULL OR Ip IS NULL THEN
        RETURN;
    END IF;
    Ip_Array := SplitNumber(Ip, '.');
    Mask_Array := SplitNumber(SubnetMask, '.');
    FOR i IN 1..4 LOOP
        SubnetBin := NULL;
        BroadcastBin := NULL;
        FOR m IN 1..8 LOOP
            IF SUBSTR(LPAD(Dec2Base(Ip_Array(i), BASE_BIN), 8, '0'), m, 1) = 1 
                AND SUBSTR(LPAD(Dec2Base(Mask_Array(i), BASE_BIN), 8, '0'), m, 1) = 1 THEN
                SubnetBin := SubnetBin ||'1';
            ELSE
                SubnetBin := SubnetBin ||'0';
            END IF;         
            IF SUBSTR(LPAD(Dec2Base(Mask_Array(i), BASE_BIN), 8, '0'), m, 1) = 1 THEN
                BroadcastBin := SubnetBin;
            ELSE
                BroadcastBin := BroadcastBin ||'1';
            END IF;         
        END LOOP;
        Subnet := Subnet ||'.'||Base2Dec(SubnetBin, BASE_BIN);
        BroadcastIp := BroadcastIp ||'.'||Base2Dec(BroadcastBin, BASE_BIN);
    END LOOP;
    Subnet := SUBSTR(Subnet, 2);
    BroadcastIp := SUBSTR(BroadcastIp, 2);  
END GetIpSubnet;




END IP_Utility;
/

或在oracle PL/SQL how to calculate range ip for IPv6 cidr查看此软件包的高级版本

【讨论】:

  • 感谢 Wernfried 提供上述信息。我会通过它,尝试一下,让你知道它是否可以解决问题。
猜你喜欢
  • 1970-01-01
  • 2014-07-31
  • 2016-04-09
  • 2022-07-22
  • 2018-10-08
  • 2018-03-09
  • 2020-10-07
  • 2017-11-27
  • 2010-09-10
相关资源
最近更新 更多