2121# along with this program. If not, see <http://www.gnu.org/licenses/>.
2222
2323from __future__ import absolute_import , division , print_function
24+ import ipaddress
25+
26+ from firewall .functions import check_mac
2427
2528__metaclass__ = type
2629
@@ -343,6 +346,39 @@ def try_set_zone_of_interface(module, _zone, interface):
343346 return (False , False )
344347
345348
349+ # Check that all of the ipset entries are ipv4, ipv6, or mac addresses
350+ # if not, fail the module
351+ # if they are, return "ipv4", "ipv6", or "mac"
352+ def validate_ipset_entries (ipset_entries , module ):
353+ addr_type = None
354+ is_mixed_addr_types = False
355+ for entry in ipset_entries :
356+ if check_mac (entry ):
357+ if addr_type is None :
358+ addr_type = "mac"
359+ elif addr_type != "mac" :
360+ is_mixed_addr_types = True
361+ else :
362+ addr = ipaddress .ip_interface (entry )
363+ if addr .version == 4 :
364+ if addr_type is None :
365+ addr_type = "ipv4"
366+ elif addr_type != "ipv4" :
367+ is_mixed_addr_types = True
368+ elif addr .version == 6 :
369+ if addr_type is None :
370+ addr_type = "ipv6"
371+ elif addr_type != "ipv6" :
372+ is_mixed_addr_types = True
373+ else :
374+ module .fail_json (msg = "Invalid IP address - " + entry )
375+ if is_mixed_addr_types :
376+ module .fail_json (
377+ msg = "Address types cannot be mixed in ipset entries - " + str (ipset_entries )
378+ )
379+ return addr_type
380+
381+
346382# Above: adapted from firewall-cmd source code
347383
348384
@@ -613,13 +649,14 @@ def set_service(
613649 else :
614650 self .module .fail_json (msg = "INVALID SERVICE - " + item )
615651
616- def _create_ipset (self , ipset , ipset_type ):
652+ def _create_ipset (self , ipset , ipset_type , ipset_options ):
617653 if not ipset_type :
618654 self .module .fail_json (msg = "ipset_type needed when creating a new ipset" )
619655
620656 fw_ipset = None
621657 fw_ipset_settings = FirewallClientIPSetSettings ()
622658 fw_ipset_settings .setType (ipset_type )
659+ fw_ipset_settings .setOptions (ipset_options )
623660 if not self .module .check_mode :
624661 self .fw .config ().addIPSet (ipset , fw_ipset_settings )
625662 fw_ipset = self .fw .config ().getIPSetByName (ipset )
@@ -628,6 +665,14 @@ def _create_ipset(self, ipset, ipset_type):
628665 return fw_ipset , fw_ipset_settings
629666
630667 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
668+ addr_type = validate_ipset_entries (ipset_entries , self .module )
669+ if addr_type is None and ipset_entries :
670+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
671+ ipset_options = {}
672+ if addr_type == "ipv6" :
673+ ipset_options = {
674+ "family" : "inet6" ,
675+ }
631676 ipset_exists = ipset in self .fw .config ().getIPSetNames ()
632677 fw_ipset = None
633678 fw_ipset_settings = None
@@ -641,7 +686,9 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
641686 % (ipset , fw_ipset_settings .getType ())
642687 )
643688 elif self .state == "present" :
644- fw_ipset , fw_ipset_settings = self ._create_ipset (ipset , ipset_type )
689+ fw_ipset , fw_ipset_settings = self ._create_ipset (
690+ ipset , ipset_type , ipset_options
691+ )
645692 self .changed = True
646693 ipset_exists = True
647694 if self .state == "present" :
@@ -1256,6 +1303,12 @@ def set_service(
12561303 self .change ("--zone" , self .zone , op + item )
12571304
12581305 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
1306+ addr_type = validate_ipset_entries (ipset_entries , self .module )
1307+ if addr_type is None and ipset_entries :
1308+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
1309+ ipset_options = []
1310+ if addr_type == "ipv6" :
1311+ ipset_options = ["--option" , "family=inet6" ]
12591312 present = self .check_state (["present" , "absent" ], "ipset" )
12601313 known_ipsets = self .cmd ("--get-ipsets" ).split ()
12611314 ipset_exists = ipset in known_ipsets
@@ -1280,7 +1333,7 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
12801333 self .module .fail_json (
12811334 msg = "ipset_type needed when creating a new ipset"
12821335 )
1283- self .change ("--new-ipset" , ipset , "--type=%s" % ipset_type )
1336+ self .change ("--new-ipset" , ipset , "--type=%s" % ipset_type , * ipset_options )
12841337
12851338 existing_description = self .cmd ("--ipset" , ipset , "--get-description" )
12861339 if description is not None and description != existing_description :
0 commit comments