I'm trying to write a regex for accepting IPv6 subnet from 8000::
to ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
. The subnet is based on the prefix range between /1 - 128
Example list of valid netmask for IPv6:
The prefix /1 is equal to netmask 8000::
The prefix /2 is equal to netmask c000::
The prefix /3 is equal to netmask e000::
The prefix /4 is equal to netmask f000::
The prefix /5 is equal to netmask f800::
The prefix /6 is equal to netmask fc00::
The prefix /7 is equal to netmask fe00::
The prefix /8 is equal to netmask ff00::
The prefix /9 is equal to netmask ff80::
The prefix /10 is equal to netmask ffc0::
The prefix /11 is equal to netmask ffe0::
The prefix /12 is equal to netmask fff0::
The prefix /13 is equal to netmask fff8::
The prefix /14 is equal to netmask fffc::
The prefix /15 is equal to netmask fffe::
The prefix /16 is equal to netmask ffff::
The prefix /17 is equal to netmask ffff:8000::
The prefix /18 is equal to netmask ffff:c000::
The prefix /19 is equal to netmask ffff:e000::
The prefix /20 is equal to netmask ffff:f000::
The prefix /21 is equal to netmask ffff:f800::
The prefix /22 is equal to netmask ffff:fc00::
The prefix /23 is equal to netmask ffff:fe00::
The prefix /24 is equal to netmask ffff:ff00::
The prefix /25 is equal to netmask ffff:ff80::
The prefix /26 is equal to netmask ffff:ffc0::
The prefix /27 is equal to netmask ffff:ffe0::
The prefix /28 is equal to netmask ffff:fff0::
The prefix /29 is equal to netmask ffff:fff8::
The prefix /30 is equal to netmask ffff:fffc::
The prefix /31 is equal to netmask ffff:fffe::
The prefix /32 is equal to netmask ffff:ffff::
The prefix /33 is equal to netmask ffff:ffff:8000::
The prefix /34 is equal to netmask ffff:ffff:c000::
The prefix /35 is equal to netmask ffff:ffff:e000::
The prefix /36 is equal to netmask ffff:ffff:f000::
The prefix /37 is equal to netmask ffff:ffff:f800::
The prefix /38 is equal to netmask ffff:ffff:fc00::
The prefix /39 is equal to netmask ffff:ffff:fe00::
The prefix /40 is equal to netmask ffff:ffff:ff00::
The prefix /41 is equal to netmask ffff:ffff:ff80::
The prefix /42 is equal to netmask ffff:ffff:ffc0::
The prefix /43 is equal to netmask ffff:ffff:ffe0::
The prefix /44 is equal to netmask ffff:ffff:fff0::
The prefix /45 is equal to netmask ffff:ffff:fff8::
The prefix /46 is equal to netmask ffff:ffff:fffc::
The prefix /47 is equal to netmask ffff:ffff:fffe::
The prefix /48 is equal to netmask ffff:ffff:ffff::
The prefix /49 is equal to netmask ffff:ffff:ffff:8000::
The prefix /50 is equal to netmask ffff:ffff:ffff:c000::
The prefix /51 is equal to netmask ffff:ffff:ffff:e000::
The prefix /52 is equal to netmask ffff:ffff:ffff:f000::
The prefix /53 is equal to netmask ffff:ffff:ffff:f800::
The prefix /54 is equal to netmask ffff:ffff:ffff:fc00::
The prefix /55 is equal to netmask ffff:ffff:ffff:fe00::
The prefix /56 is equal to netmask ffff:ffff:ffff:ff00::
The prefix /57 is equal to netmask ffff:ffff:ffff:ff80::
The prefix /58 is equal to netmask ffff:ffff:ffff:ffc0::
The prefix /59 is equal to netmask ffff:ffff:ffff:ffe0::
The prefix /60 is equal to netmask ffff:ffff:ffff:fff0::
The prefix /61 is equal to netmask ffff:ffff:ffff:fff8::
The prefix /62 is equal to netmask ffff:ffff:ffff:fffc::
The prefix /63 is equal to netmask ffff:ffff:ffff:fffe::
The prefix /64 is equal to netmask ffff:ffff:ffff:ffff::
The prefix /65 is equal to netmask ffff:ffff:ffff:ffff:8000::
The prefix /66 is equal to netmask ffff:ffff:ffff:ffff:c000::
The prefix /67 is equal to netmask ffff:ffff:ffff:ffff:e000::
The prefix /68 is equal to netmask ffff:ffff:ffff:ffff:f000::
The prefix /69 is equal to netmask ffff:ffff:ffff:ffff:f800::
The prefix /70 is equal to netmask ffff:ffff:ffff:ffff:fc00::
The prefix /71 is equal to netmask ffff:ffff:ffff:ffff:fe00::
The prefix /72 is equal to netmask ffff:ffff:ffff:ffff:ff00::
The prefix /73 is equal to netmask ffff:ffff:ffff:ffff:ff80::
The prefix /74 is equal to netmask ffff:ffff:ffff:ffff:ffc0::
The prefix /75 is equal to netmask ffff:ffff:ffff:ffff:ffe0::
The prefix /76 is equal to netmask ffff:ffff:ffff:ffff:fff0::
The prefix /77 is equal to netmask ffff:ffff:ffff:ffff:fff8::
The prefix /78 is equal to netmask ffff:ffff:ffff:ffff:fffc::
The prefix /79 is equal to netmask ffff:ffff:ffff:ffff:fffe::
The prefix /80 is equal to netmask ffff:ffff:ffff:ffff:ffff::
The prefix /81 is equal to netmask ffff:ffff:ffff:ffff:ffff:8000::
The prefix /82 is equal to netmask ffff:ffff:ffff:ffff:ffff:c000::
The prefix /83 is equal to netmask ffff:ffff:ffff:ffff:ffff:e000::
The prefix /84 is equal to netmask ffff:ffff:ffff:ffff:ffff:f000::
The prefix /85 is equal to netmask ffff:ffff:ffff:ffff:ffff:f800::
The prefix /86 is equal to netmask ffff:ffff:ffff:ffff:ffff:fc00::
The prefix /87 is equal to netmask ffff:ffff:ffff:ffff:ffff:fe00::
The prefix /88 is equal to netmask ffff:ffff:ffff:ffff:ffff:ff00::
The prefix /89 is equal to netmask ffff:ffff:ffff:ffff:ffff:ff80::
The prefix /90 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffc0::
The prefix /91 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffe0::
The prefix /92 is equal to netmask ffff:ffff:ffff:ffff:ffff:fff0::
The prefix /93 is equal to netmask ffff:ffff:ffff:ffff:ffff:fff8::
The prefix /94 is equal to netmask ffff:ffff:ffff:ffff:ffff:fffc::
The prefix /95 is equal to netmask ffff:ffff:ffff:ffff:ffff:fffe::
The prefix /96 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff::
The prefix /97 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:8000:0
The prefix /98 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:c000:0
The prefix /99 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:e000:0
The prefix /100 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:f000:0
The prefix /101 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:f800:0
The prefix /102 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:fc00:0
The prefix /103 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:fe00:0
The prefix /104 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ff00:0
The prefix /105 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ff80:0
The prefix /106 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffc0:0
The prefix /107 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffe0:0
The prefix /108 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:fff0:0
The prefix /109 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:fff8:0
The prefix /110 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:fffc:0
The prefix /111 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:fffe:0
The prefix /112 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:0
The prefix /113 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000
The prefix /114 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:c000
The prefix /115 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:e000
The prefix /116 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:f000
The prefix /117 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:f800
The prefix /118 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:fc00
The prefix /119 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:fe00
The prefix /120 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00
The prefix /121 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80
The prefix /122 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffc0
The prefix /123 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0
The prefix /124 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0
The prefix /125 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8
The prefix /126 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc
The prefix /127 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe
The last prefix /128 is equal to netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
That means if a user gives an input (netmask) 8000::
, then the regex will validate it as valid
and if he gives an input (netmask) 800a::
the regex will say it is invalid as it is not in that netmask range above
This is the current regex that I came up with:
- This output shows
correct
and this is ok
#This is netmask given by user:
ipv6_netmask_given="c000:0000:0000:0000:0000:0000:0000:0000" # equal to c000:: and it is inside the range
ipv6_netmask_regex='^([0-9a-fA-F]{1,4}:){7}([0-9a-fA-F]{1,4})$'
if [[ ${ipv6_netmask_given} =~ ${ipv6_netmask_regex} ]]; then
echo "correct"
else
echo "invalid netmask"
fi
# output: correct
- This output shows
correct
but itSHOULD NOT
as the given netmaskcf01::
is not in the netmask range
# This is netmask given by user:
ipv6_netmask_given="cf01:0000:0000:0000:0000:0000:0000:0000"
ipv6_netmask_regex='^([0-9a-fA-F]{1,4}:){7}([0-9a-fA-F]{1,4})$'
if [[ ${ipv6_netmask_given} =~ ${ipv6_netmask_regex} ]]; then
echo "correct"
else
echo "invalid netmask"
fi
# output: correct
# expected output: invalid netmask
I know the regex is too generic here but how do I make sure that the regex can only accept the valid netmasks between 1 to 128 IPs?
If I use IPv4, I have no issue as I can solve the similar problem that I'm having right now. For example, this is for IPv4 regex to validate netmasks and it is working fine:
'^(128|192|224|240|248|252|254|255)\.0\.0\.0|255\.(0|128|192|224|240|248|252|254|255)\.0\.0|255\.255\.(0|128|192|224|240|248|252|254|255)\.0|255\.255\.255\.(0|128|192|224|240|248|252|254|255)$'
The above regex accepts 32 IPs between 128.0.0.0
to 255.255.255.255
netmasks. So, it will not accept an subnet/netmask IP from a user that is not in the subnet/netmask list like 128.0.0.1
:
But for IPv6 how do improve my regex so it will validate the IPv6 subnets correctly?
In brief from my question above:
How do I tell regex to accept only the list of netmask range list that I posted above?
Thanks
CodePudding user response:
You could deal with the multiple requirements in two steps, here with a strict adherence to the first list you have given (only those match):
A pattern for ensuring the input consists of a series of colons and F's, followed by one of "8CEF", followed by a series of zeroes, possibly followed by "::" or by ":0"
^[fF:]*[8cCeEfF]0*(?::[0:])?$
A pattern that requires that colons appear at fixed positions, and only there:
^(?:(?:[^:]{4}:){1,6}:|(?:[^:]{4}:){7}(?:0|[^:]{4}))$
So your script could require that the input is validated by both regexes:
ipv6_netmask_regex1='^[fF:]*[8cCeEfF]0*(:[0:])?$'
ipv6_netmask_regex2='^(([^:]{4}:){1,6}:|([^:]{4}:){7}(0|[^:]{4}))$'
if [[ ${ipv6_netmask_given} =~ ${ipv6_netmask_regex1}
&& ${ipv6_netmask_given} =~ ${ipv6_netmask_regex2} ]];
then
# ...etc
Here is how it would work to allow for more zeroes:
ipv6_netmask_regex1='^[fF:]*[8cCeEfF][0:]*$'
ipv6_netmask_regex2='^((([^:]{4}|0{1,4}):){1,6}:|(([^:]{4}|0{1,4}):){7}([^:]{4}|0{1,4}))$'
if [[ ${ipv6_netmask_given} =~ ${ipv6_netmask_regex1}
&& ${ipv6_netmask_given} =~ ${ipv6_netmask_regex2} ]]; then
# etc