Home > front end >  (Alternate Solution) Validate IPV4 and IPV6 with wildcard (*) characters using Regex
(Alternate Solution) Validate IPV4 and IPV6 with wildcard (*) characters using Regex

Time:12-16

I want to validate IP Address with wildcard characters (*) using regex. I came up with the following regex for IPV4 and IPV6 but these don't validate all use cases.

IPV4

^((([0-9]{1,2})|(1[0-9]{2,2})|(2[0-4][0-9])|(25[0-5])|*).){3}(([0-9]{1,2})|(1[0-9]{2,2})|(2[0-4][0-9])|(25[0-5])|*)$

This regex does not match the following four valid IPV4 formats (https://regex101.com/r/RXf5yM/1). I'm not sure what I have to change to allow these.

192.*
192.0.*
192.*.2
*

IPV6

^\s*((((([0-9A-Fa-f]{1,4})|*):){7}((([0-9A-Fa-f]{1,4})|*)|:))|(((([0-9A-Fa-f]{1,4})|*):){6}(:(([0-9A-Fa-f]{1,4})|*)|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(((([0-9A-Fa-f]{1,4})|*):){5}(((:(([0-9A-Fa-f]{1,4})|*)){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(((([0-9A-Fa-f]{1,4})|*):){4}(((:(([0-9A-Fa-f]{1,4})|*)){1,3})|((:(([0-9A-Fa-f]{1,4})|*))?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(((([0-9A-Fa-f]{1,4})|*):){3}(((:(([0-9A-Fa-f]{1,4})|*)){1,4})|((:(([0-9A-Fa-f]{1,4})|*)){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(((([0-9A-Fa-f]{1,4})|*):){2}(((:(([0-9A-Fa-f]{1,4})|*)){1,5})|((:(([0-9A-Fa-f]{1,4})|*)){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(((([0-9A-Fa-f]{1,4})|*):){1}(((:(([0-9A-Fa-f]{1,4})|*)){1,6})|((:(([0-9A-Fa-f]{1,4})|*)){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:(([0-9A-Fa-f]{1,4})|*)){1,7})|((:(([0-9A-Fa-f]{1,4})|*)){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))\s*$

This regex does not match the following three valid IPV6 formats.(https://regex101.com/r/ereIrE/1)

2001:DB8:0:0:0:*
2001:*:1
*

But it matches an invalid IPV6 value with "::*" -> 2404:66:4003::*:804

I need to modify the regex to allow only valid values. I'm new to regex and IP Address concepts and not able to figure this out. I need to do the validation in both JS and Java. Please help me.

CodePudding user response:

Based on the suggestions in the question comments, I have given the solution for validating IP Addresses for IPV6 and IPV4. I've validated this by splitting the IP Address. PS - I've used IPV6 Examples with a few formats that I've come across. Please let me know if I've missed any use cases.

IPV6

function evalIp6(ipAddress) {
    var ipAddrList = ipAddress.split(":")     
    var count =ipAddress.split("::").length-1;   
    if(ipAddrList.length>8 && !(ipAddress.split(":").length == 9 && ipAddrList[ipAddrList.length-1]=="" && count == 1 ))
            //IPV6 Cannot have more than 8 groups
            //Second if check to allow '::' in end after 7 groups. Eg : 2001:db8:122:344:c0:2:2100::
     {
      return false;
     }
    if(count>1)//IPV6 cannot have more that one "::"
    {
        return false;
    }
   
    if(ipAddress.indexOf("::*") != -1 || ipAddress.indexOf("*::") != -1)//IPV6 cannot have consecutive wildcard(*) with "::" since it can have multiple combinations.
    {
      return false;
    } 
    var isWildCardPresent = false;
    for (let i = 0; i < ipAddrList.length; i  ) {

        if(!isIPV6Group(ipAddrList[i]))
        {
            return false;
        }
        if(ipAddrList[i]  == "*")
        {
            isWildCardPresent = true;
        }
        
    }
   if(!isWildCardPresent && count == 0 && ipAddrList.length!=8)//Without wildcard and :: , less. than 8 groups present. So it is invalid.
   {
        return false;
   }
   
   
    return true
}


function isIPV6Group(x)
{
    var ipv6GroupRegex = "^(([0-9A-Fa-f]{1,4})|\\*|)$";
    //Allows Numbers 0 to FFFF or * or empty string (for group between ::)
  ipv6GroupRegex = new RegExp(ipv6GroupRegex);

  return ipv6GroupRegex.test(x);
}




var IPAddrTestList = [
"2404:6800:4003:c02::8a",
"2404:6800:4003:804::200e",
"2001:4998:c:a06::2:4008",
"fe80::21d8:f50:c295:c4be",
"2001:cdba::e:9652",
"2001:cdba:0:0:0:0:3257:9652",
"2001:cdba::3257:9652",
"2001:cdba::1222",
"21DA:D3:0:2F3B:2AA:FF:FE28:9C5A",
"2001:cdba::1:2:3:3257:9652",
"1234:Fd2:2:1:89::4500",
"1234:Fd2:12:1:89::4500",
"1080:0:0:0:8:800:200C:417A",
"1080::8:800:200C:417A",
"3210::",
"::",
"2001:B07:6473:B409:C05C:AC2B:C9B9:CC42",
"2A0C:9A40:8170::1",
"64:FF9B::CD8B:6384",
"FE80::4ABA:4EFF:FED4:6455",
"FE80::3E5C:C4FF:FE3B:AC19",
"FE80::3E5C:C4FF:FEA6:D45D",
"FE80::266:86FF:FE05:7933",
"2A03:2880:F127:83:FACE:B00C:0:25DE",
"2A00:5A60::AD1:FF",
"a:b::",
"2001:470:b0b4:1:280:c6ff:fef2:9410",
"2001:868:100::3",
"2001:888:144a::a441:888:1002",
"::1",
"2001:db8:122:3c0:0:221::",
"2001:db8:122:c000:2:2100::",
"2001:db8:1c0:2:21::",
"2001:db8:c000:221::",
"2001:db8:122:344:c0:2:2100::",


//IPV6 With wildcard
"2001:DB8:0:0:0:*:*:*",
"2001:DB8::0:*",
"2001:DB8:0:0:0:*:0:1",
"2001:DB8:0:0:0:*",
"2001:*:1",
"*",

//After this everything invalid
"2404:66:4003::*:804",
"2404:66:4003:34:*:804:35:35:35",


//Invalid IPV6 without wildcard
"2404::4003:804::200e",
"2001:cdba:e:9652",
"2404:6800:40003:c02::8a",
"1:2:3:4:5:6:7:8:9",
"a::b::c",
"x:x:x:x:x:x:x:x",
"::2222:3333:4444:5555:7777:8888::",

//IPV4 mapped with IPV6
"::FFFF:1.2.3.4",
"2001:db8:122:344::192.0.2.33",
"64:ff9b::192.0.2.33",
"::FFFF:189.203.69.53",
"::FFFF:94.8.43.194",
"::FFFF:174.238.136.77",
"::FFFF:142.234.162.5"
]
var result = "";
for(var index=0;index<IPAddrTestList.length;index  )
{
  var resultObj = IPAddrTestList[index]   "---->"   evalIp6(IPAddrTestList[index]);  
  result = result resultObj '<br>';
 
}
document.getElementById("demo").innerHTML = result;
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
</body>
</html>

IPV4

@Maximillian Dolbaum's code works pretty good. I've slightly tweaked his code to fit my requirements.

function evalIpv4(str) {
    var arr = str.split(".")
   
   var isWildCardPresent = false;
    for (var i = 0; i < arr.length; i  ) {
            if(arr[i] === '*')
        {
             isWildCardPresent = true;
        }
        if (!(arr[i] === '*' || inRange(parseInt(arr[i]), 0, 255))) {
            return false
        }
    }
    if(arr.length < 4 && !isWildCardPresent)//Less than 4 digits present without wildcard
    {
        return false;
    }
    return true
}

function inRange(x, min, max) {
    return x >= min && x <= max;
}



var IPAddrTestList = [
"192.192.192.192",
"*.*.1.1",
"*.1.1.*",
"*.*.1.*",
"192.*.23.34",
"*.192.23.*",
"192.0.*.0",
"192.*.*.*",
"192.*",//equal to 192.*.*.*
"192.0.*",//equal to 192.0.*.*
"*",//equal to *.*.*.*
"19.*.23",//equal to 19.*.23.*
"*.24.23",//equal to *.24.23.*,
"192.12",//false - less than 4 octets
"256.23.23.34"//false - 1st octet > 255
]

var result = "";
for(var index=0;index<IPAddrTestList.length;index  )
{
  var resultObj = IPAddrTestList[index]   "---->"   evalIpv4(IPAddrTestList[index]);  
  result = result resultObj '<br>';
 
}
document.getElementById("demo").innerHTML = result;
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
</body>
</html>

  • Related