Search code examples
luapattern-matchingip-addressipv6ipv4

Lua function check if ipv4 or ipv6 or string


I'd like to have a function that I can pass a whitespace trimmed string to and it will return
0 for error (not a string) 1 for ipv4 2 for ipv6 3 for a string thats not an ip.

Ipv6 has these rules:

Ipv6 is represented by 8 groups of 16-bit hexadecimal values separated by colons (:)
The hexadecimal digits are case-insensitive
Abbreviation rules:
1: Omit leading zeroes in a 16-bit value
2: Replace one or more groups of consecutive zeroes by a double colon

wiki example showing 3 ways that are all the same ipv6:

fe80:0000:0000:0000:0202:b3ff:fe1e:8329
fe80:0:0:0:202:b3ff:fe1e:8329
fe80::202:b3ff:fe1e:8329 

I'm reasonably sure for ipv4 you just check for three . then check the string is all
numbers and the .'s are counted as numbers and the last check for just a string
would be at the end of an if statement so if its not ipv4/6 and its a string then
it returns 3


Solution

  • this seems like a pretty basic problem to solve. i think this function does what you need...

    function GetIPType(ip)
        -- must pass in a string value
        if ip == nil or type(ip) ~= "string" then
            return 0
        end
    
        -- check for format 1.11.111.111 for ipv4
        local chunks = {ip:match("(%d+)%.(%d+)%.(%d+)%.(%d+)")}
        if (#chunks == 4) then
            for _,v in pairs(chunks) do
                if (tonumber(v) < 0 or tonumber(v) > 255) then
                    return 0
                end
            end
            return 1
        else
            return 0
        end
    
        -- check for ipv6 format, should be 8 'chunks' of numbers/letters
        local _, chunks = ip:gsub("[%a%d]+%:?", "")
        if chunks == 8 then
            return 2
        end
    
        -- if we get here, assume we've been given a random string
        return 3
    end
    

    tested it with this code:

    local IPType = {
        [0] = "Error",
        [1] = "IPv4",
        [2] = "IPv6",
        [3] = "string",
    }
    
    
    local ips = {
        "128.1.0.1",        -- ipv4
        "223.255.254.254",  -- ipv4
        "999.12345.0.0001",     -- invalid ipv4
        "1050:0:0:0:5:600:300c:326b",               -- ipv6
        "1050:0000:0000:0000:0005:0600:300c:326b",  -- ipv6
        "1050:::600:5:1000::",  -- contracted ipv6
        "129.garbage.9.1",  -- string
        129.10              -- error
    }
    
    for k,v in pairs(ips) do
        print(v, IPType[GetIPType(v)])
    end
    

    which generated this output:

    128.1.0.1   IPv4
    223.255.254.254 IPv4
    1050:0:0:0:5:600:300c:326b  IPv6
    1050:0000:0000:0000:0005:0600:300c:326b IPv6
    129.garbage.9.1 string
    129.1   Error
    

    in the future, you'll get more helpful feedback if you actually post the code you've attempted to write to solve your particular problem, and let us know where you need help. SO isn't a personal code writing service, as stated in the faq. however, i'll give you the benefit of the doubt since you look new and this is something that could potentially benefit other people. the code above is basic, so feel free to update it if it doesn't catch fringe test cases i don't know about.