2017-07-13 4 views
-1

Vous recherchez pl \ sql (env Oracle.) Fonction de conversion qui excepte une chaîne en entrée (format IPV4) et retourne le format IPV6, par exemple:PLSQL Fonction pour convertir IPV4 à IPV6

Envoyer - 10,85. 79,96 retournera 0: 0: 0: 0: 0: ffff: A55: 4f60

Merci pour l'aide.

+4

Je ne sais pas ce que vous prévoyez de l'utiliser pour, mais s'il vous plaît être conscient que la conversion comme cela ne vaut que dans des circonstances très spécifiques (les sockets IPv6 acceptant les connexions IPv4) et qu'il n'y a généralement pas de relation visible entre les adresses IPv4 et IPv6. (S'assurer juste que tout le monde lisant cette question comprend cela :) –

Répondre

3

Vous pouvez utiliser cet ensemble de fonctions:

FUNCTION UncompressIpV6(Ip IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS 
    IpFull VARCHAR2(40); 
    len INTEGER := 7; 
BEGIN 
    IF REGEXP_LIKE(Ip, '::') THEN 
     IpFull := REGEXP_REPLACE(REGEXP_REPLACE(Ip, '^::', '0::'), '::$', '::0'); 
     IF REGEXP_LIKE(Ip, ':\d+\.\d+\.\d+\.\d+$') THEN 
      -- Mixed notation, e.g.: 0::FFFF:129.144.52.38 
      len := 6; 
     END IF; 
     WHILE REGEXP_COUNT(IpFull, ':') <= len LOOP 
      IpFull := REGEXP_REPLACE(IpFull, '::', ':0::'); 
     END LOOP; 
     RETURN REGEXP_REPLACE(IpFull, '::', ':'); 
    ELSE 
     RETURN Ip; 
    END IF; 

END UncompressIpV6; 



FUNCTION Ip2Decimal(IP IN VARCHAR2) RETURN NUMBER DETERMINISTIC IS 
    DecimalIp NUMBER := 0; 
BEGIN 

    IF REGEXP_LIKE(IP, ':') THEN 
     IF REGEXP_LIKE(IP, '\d+\.\d+\.\d+\.\d+$') THEN 
      -- Mixed notation, e.g.: 0:0:0:0:0:FFFF:129.144.52.38 
      SELECT SUM(TO_NUMBER(REGEXP_SUBSTR(UncompressIpV6(IP), '[[:xdigit:]]+', 1, LEVEL), 'XXXX') * POWER(65536, 8-LEVEL)) 
      INTO DecimalIp 
      FROM dual 
      CONNECT BY LEVEL <= 6; 

      SELECT DecimalIp + SUM(REGEXP_SUBSTR(REGEXP_SUBSTR(UncompressIpV6(IP), '\d+\.\d+\.\d+\.\d+$'), '\d+', 1, LEVEL) * POWER(256, 4-LEVEL)) 
      INTO DecimalIp 
      FROM dual 
      CONNECT BY LEVEL <= 4; 
      RETURN DecimalIp;  
     ELSE 
      SELECT SUM(TO_NUMBER(REGEXP_SUBSTR(UncompressIpV6(IP), '[[:xdigit:]]+', 1, LEVEL), 'XXXX') * POWER(65536, 8-LEVEL)) 
      INTO DecimalIp 
      FROM dual 
      CONNECT BY LEVEL <= 8; 
      RETURN DecimalIp; 
     END IF; 
    ELSE 
     SELECT SUM(REGEXP_SUBSTR(IP, '\d+', 1, LEVEL) * POWER(256, 4-LEVEL)) 
     INTO DecimalIp 
     FROM dual 
     CONNECT BY LEVEL <= 4; 
     RETURN DecimalIp; 
    END IF; 

END Ip2Decimal; 




FUNCTION Decimal2Ip(IpDecimal IN NUMBER) RETURN VARCHAR2 DETERMINISTIC IS 

    IP VARCHAR2(16); 
    Octet INTEGER; 
    v_IpDecimal INTEGER := IpDecimal; 

BEGIN 
    IF IpDecimal IS NULL THEN 
     RETURN NULL; 
    END IF; 
    IF IpDecimal > 2**32 - 1 THEN 
     RAISE NUMERIC_OVERFLOW; 
    END IF; 

    FOR i IN 1..4 LOOP 
     Octet := TRUNC(v_IpDecimal/256**(4-i)); 
     v_IpDecimal := v_IpDecimal - Octet * 256**(4-i); 
     IP := IP ||'.'||Octet; 
    END LOOP; 
    RETURN SUBSTR(IP, 2); 

END Decimal2Ip; 



FUNCTION Decimal2IPv6(IpDecimal IN NUMBER) RETURN VARCHAR2 DETERMINISTIC IS 

    IP VARCHAR2(40); 
    Octet INTEGER; 
    v_IpDecimal NUMBER := IpDecimal; 

BEGIN 
    IF IpDecimal IS NULL THEN 
     RETURN NULL; 
    END IF; 
    IF IpDecimal > 2**128 - 1 THEN 
     RAISE NUMERIC_OVERFLOW; 
    END IF; 

    FOR i IN 1..8 LOOP 
     Octet := TRUNC(v_IpDecimal/65536**(8-i)); 
     v_IpDecimal := v_IpDecimal - Octet * 65536**(8-i); 
     IP := IP ||':'||TO_CHAR(Octet, 'fmXXXX'); 
    END LOOP; 
    RETURN LOWER(SUBSTR(IP, 2)); 

END Decimal2IPv6; 

Exemple:

SELECT REGEXP_REPLACE(Decimal2IPv6(Ip2Decimal('10.85.79.96')), ':0:', ':ffff:', 1, 3) 
FROM dual; 

0:0:0:0:0:ffff:a55:4f60