Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6232713
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T10:09:51+00:00 2026-05-24T10:09:51+00:00

Any have any good code for converting a IPv6 address string into an integer?

  • 0

Any have any good code for converting a IPv6 address string into an integer? Converting IPv4 seems to be fairly easy, with the one format. However, IPv6 has several different formats to show an address:

  • XXXX:XXXX:XXXX:XXXX::
  • XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX
  • XXXX:XXX:XXXX:0:0:XXXX:XXX:XXXX
  • XXXX:XXX:XXXX::XXXX:XXX:XXXX
  • ::ffff:XXXX:XXX (IPv4 in v6 format)
  • ::ffff:###.#.#.### (also valid IPv4 in v6 format)

I’d like to be able to take one of these strings and translate it into an INTEGER for IP-to-network matching, and allow for any of these formats as the input.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T10:09:52+00:00Added an answer on May 24, 2026 at 10:09 am

    Ended up rolling my own. Also realized that Oracle’s 126-bit INTEGER is not enough bits for IPv6’s 128-bit addresses. Frankly, I don’t know how the original C library’s INET6_ATON (or INET_PTON) does it, considering that I’ve never heard of a 16-byte integer.

    I ended up with a 32-byte hex string, which means I have to do some fancy “half-string” math on nettohex and use SUBSTR for the FBIs to work correctly. (Blasted PL/SQL doesn’t allow for “RETURN CHAR(32)”…)

    Overall, though, it works well, works in all formats, and allows for index-based character comparisons to find out if an IP address is within an IP range.

    Here’s the full code:

    CREATE OR REPLACE FUNCTION ipguess(
       ip_string IN VARCHAR2
    ) RETURN NATURAL
    DETERMINISTIC
    IS
    BEGIN
       -- Short-circuit the most popular, and also catch the special case of IPv4 addresses in IPv6
       IF    REGEXP_LIKE(ip_string, '\d{1,3}(\.\d{1,3}){3}')                       THEN RETURN 4;
       ELSIF REGEXP_LIKE(ip_string, '[[:xdigit:]]{0,4}(\:[[:xdigit:]]{0,4}){0,7}') THEN RETURN 6;
       ELSE                                                                             RETURN NULL;
       END IF;
    END ipguess;
    
    CREATE OR REPLACE FUNCTION iptohex(
       ip_string IN VARCHAR2
    ) RETURN CHAR     -- INTEGER only holds 126 binary digits, IPv6 has 128
    DETERMINISTIC
    IS
       iptype NATURAL := ipguess(ip_string);
       ip     VARCHAR2(32);
       ipwork VARCHAR2(64);
       d      INTEGER;
       q      VARCHAR2(3);
    BEGIN
       IF    iptype = 4 THEN
          -- Sanity check
          ipwork := REGEXP_SUBSTR(ip_string, '\d{1,3}(\.\d{1,3}){3}');
          IF ipwork IS NULL THEN RETURN NULL; END IF;
    
          -- Starting prefix
          -- NOTE: 2^48 - 2^32 = 281470681743360 = ::ffff:0.0.0.0
          --       (for compatibility with IPv4 addresses in IPv6)
          ip := '00000000000000000000ffff';
    
          -- Parse the input
          WHILE LENGTH(ipwork) IS NOT NULL
          LOOP
             d := INSTR(ipwork, '.');  -- find the dot
             IF d > 0 THEN             -- isolate the decimal octet
                q      := SUBSTR(ipwork, 1, d - 1);
                ipwork := SUBSTR(ipwork, d + 1);
             ELSE
                q      := ipwork;
                ipwork := '';
             END IF;
    
             -- convert to a hex string
             ip := ip || TO_CHAR(TO_NUMBER(q), 'FM0x');
    
          END LOOP;
       ELSIF iptype = 6 THEN
          -- Short-circuit "::" = 0
          IF ip_string = '::' THEN RETURN LPAD('0', 32, '0'); END IF;
    
          -- Sanity check
          ipwork := REGEXP_SUBSTR(ip_string, '[[:xdigit:]]{0,4}(\:[[:xdigit:]]{0,4}){0,7}');
          IF ipwork IS NULL THEN RETURN NULL; END IF;
    
          -- Replace leading zeros
          -- (add a bunch to all of the pairs, then remove only the required ones)
          ipwork := REGEXP_REPLACE(ipwork, '(^|\:)([[:xdigit:]]{1,4})', '\1000\2');
          ipwork := REGEXP_REPLACE(ipwork, '(^|\:)0+([[:xdigit:]]{4})',    '\1\2');
    
          -- Groups of zeroes
          -- (total length should be 32+Z, so the gap would be the zeroes)
          ipwork := REPLACE(ipwork, '::', 'Z');
          ipwork := REPLACE(ipwork, ':');
          ipwork := REPLACE(ipwork, 'Z', LPAD('0', 33 - LENGTH(ipwork), '0'));
          ip     := LOWER(ipwork);
       ELSE
          RETURN NULL;
       END IF;
    
       RETURN ip;
    
    END iptohex;
    
    CREATE OR REPLACE FUNCTION nettohex(
       ip_string IN VARCHAR2,
       cidr      IN NATURALN,
       is_end    IN SIGNTYPE DEFAULT 0
    ) RETURN CHAR
    DETERMINISTIC
    IS
       iptype   NATURAL  := ipguess(ip_string);
       iphex    CHAR(32) := iptohex(ip_string);
       iphalf1  CHAR(16) := SUBSTR(iphex, 1, 16);
       iphalf2  CHAR(16) := SUBSTR(iphex, 17);
       ipwork   CHAR(16) := iphalf2;
       cidr_exp INTEGER  := 2 ** (iptype + 1) - cidr;
       ipint    INTEGER;
       subnet   INTEGER;
       is_big   SIGNTYPE := 0;
    BEGIN
       -- Sanity checks
       IF    iptype IS NULL THEN RETURN NULL;
       ELSIF iphex  IS NULL THEN RETURN NULL;
       END IF;
    
       IF    cidr_exp >= 64  THEN is_big := 1;
       ELSIF cidr_exp = 0    THEN RETURN iphex;  -- the exact IP, such as /32 on IPv4
       ELSIF cidr_exp <  0   THEN RETURN NULL;
       ELSIF cidr_exp >  128 THEN RETURN NULL;
       END IF;
    
       -- Change some variables around if we are working with the first/largest half
       IF is_big = 1 THEN
          ipwork   := iphalf1;
          iphalf2  := TO_CHAR((2 ** 64 - 1) * is_end, 'FM0xxxxxxxxxxxxxxx');  -- either all 0 or all F
          cidr_exp := cidr_exp - 64;
       END IF;
    
       -- Normalize IP to divisions of CIDR
       subnet := 2 ** cidr_exp;
       ipint  := TO_NUMBER(ipwork, 'FM0xxxxxxxxxxxxxxx');
       -- if is_end = 1 then add one net range (then subtract one IP) to get the ending range
       ipwork := TO_CHAR(FLOOR(ipint / subnet + is_end) * subnet - is_end, 'FM0xxxxxxxxxxxxxxx');
    
       -- Re-integrate
       IF is_big = 0 THEN iphalf2 := ipwork;
       ELSE               iphalf1 := ipwork;
       END IF;
    
       RETURN SUBSTR(iphalf1 || iphalf2, 1, 32);
    
    END nettohex;
    
    -- WHERE clause:
    -- 1. BETWEEN compare:
    --    iptohex(a.ip_addy) BETWEEN nettohex(b.net_addy, b.cidr, 0) AND nettohex(b.net_addy, b.cidr, 1)
    --
    --    Requires three function-based indexes, but all of them would work, as they are all inside the tables.
    --
    -- 2. CIDR match:
    --    nettohex(a.ip_addy, b.cidr) = nettohex(b.net_addy, b.cidr)
    --
    --    Only two functions and uses exact match, but first one requires an outside variable.  Last one would be only function-based index.
    --    An FBI of iptohex(a.ip_addy) could be implemented, but it's questionable if nettohex would use that index.
    --
    -- Recommended FBIs:
    --
    -- (SUBSTR(iptohex(a.ip_addy), 1, 32))
    -- (SUBSTR(nettohex(b.ip_addy, b.cidr, 0), 1, 32), SUBSTR(nettohex(b.ip_addy, b.cidr, 1), 1, 32))
    --
    -- NOTE: Will need to use the SUBSTR form for the above WHERE clauses!
    

    UPDATE: Oracle 11g does allow for the SUBSTR entry to be put a virtual column. So, you could have columns like this:

    ip              VARCHAR2(39),
    cidr            NUMBER(2),
    ip_hex          AS (SUBSTR(iptohex(ip),           1, 32)) VIRTUAL,
    ip_nethex_start AS (SUBSTR(nettohex(ip, cidr, 0), 1, 32)) VIRTUAL,
    ip_nethex_end   AS (SUBSTR(nettohex(ip, cidr, 1), 1, 32)) VIRTUAL,
    

    And indexes like:

    CREATE INDEX foobar_iphex_idx ON foobar (ip_hex);
    CREATE INDEX foobar_ipnet_idx ON foobar (ip_nethex_start, ip_nethex_end);
    

    Using WHERE clauses like:

    a.ip_hex BETWEEN b.ip_nethex_start AND b.ip_nethex_end
    nettohex(a.ip, b.cidr) = b.ip_nethex_start  -- not as effective
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Anyone have any good urls for templates or diagram examples in Visio 2007 to
Does anyone have any good starting points for me when looking at making web
Does anyone have any good links for developing custom field and content types that
Does anyone have any good suggestions for creating a Pipe object in Java which
Does anyone have any good articles or explanations (blogs, examples) for pointer arithmetic? Figure
Does anyone have any good resources for refining my skills in developing class diagrams?
Does anyone have any good scenarios for teaching relational databases and SQL? All the
DOes anyone have any good information with regards to when to log, I was
do you have any good suggestions how to backup remote php site and mysql,
Does anyone have any good advice or experience on how to create an engine

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.