2020# You should have received a copy of the GNU General Public License
2121# along with this program. If not, see <http://www.gnu.org/licenses/>.
2222
23- from __future__ import absolute_import , division , print_function
23+ from __future__ import absolute_import , division , print_function , unicode_literals
2424
2525__metaclass__ = type
2626
283283import re
284284import os
285285
286+ try :
287+ import ipaddress
288+
289+ HAS_IPADDRESS = True
290+ except ImportError :
291+ HAS_IPADDRESS = False
292+
293+ try :
294+ from firewall .functions import check_mac
295+
296+ HAS_CHECK_MAC = True
297+ except ImportError :
298+ HAS_CHECK_MAC = False
299+
300+ def check_mac (mac ):
301+ return False
302+
303+
286304try :
287305 import firewall .config
288306
@@ -343,6 +361,42 @@ def try_set_zone_of_interface(module, _zone, interface):
343361 return (False , False )
344362
345363
364+ # Check that all of the ipset entries are ipv4, ipv6, or mac addresses
365+ # if not, fail the module
366+ # if they are, return "ipv4", "ipv6", or "mac"
367+ def validate_ipset_entries (ipset_entries , module ):
368+ addr_type = None
369+ is_mixed_addr_types = False
370+ for entry in ipset_entries :
371+ if check_mac (entry ):
372+ if addr_type is None :
373+ addr_type = "mac"
374+ elif addr_type != "mac" :
375+ is_mixed_addr_types = True
376+ else :
377+ if HAS_IPADDRESS :
378+ addr = ipaddress .ip_interface (entry )
379+ else :
380+ module .fail_json (msg = "No IP address library found" )
381+ if addr .version == 4 :
382+ if addr_type is None :
383+ addr_type = "ipv4"
384+ elif addr_type != "ipv4" :
385+ is_mixed_addr_types = True
386+ elif addr .version == 6 :
387+ if addr_type is None :
388+ addr_type = "ipv6"
389+ elif addr_type != "ipv6" :
390+ is_mixed_addr_types = True
391+ else :
392+ module .fail_json (msg = "Invalid IP address - " + entry )
393+ if is_mixed_addr_types :
394+ module .fail_json (
395+ msg = "Address types cannot be mixed in ipset entries - " + str (ipset_entries )
396+ )
397+ return addr_type
398+
399+
346400# Above: adapted from firewall-cmd source code
347401
348402
@@ -613,13 +667,14 @@ def set_service(
613667 else :
614668 self .module .fail_json (msg = "INVALID SERVICE - " + item )
615669
616- def _create_ipset (self , ipset , ipset_type ):
670+ def _create_ipset (self , ipset , ipset_type , ipset_options ):
617671 if not ipset_type :
618672 self .module .fail_json (msg = "ipset_type needed when creating a new ipset" )
619673
620674 fw_ipset = None
621675 fw_ipset_settings = FirewallClientIPSetSettings ()
622676 fw_ipset_settings .setType (ipset_type )
677+ fw_ipset_settings .setOptions (ipset_options )
623678 if not self .module .check_mode :
624679 self .fw .config ().addIPSet (ipset , fw_ipset_settings )
625680 fw_ipset = self .fw .config ().getIPSetByName (ipset )
@@ -628,6 +683,14 @@ def _create_ipset(self, ipset, ipset_type):
628683 return fw_ipset , fw_ipset_settings
629684
630685 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
686+ addr_type = validate_ipset_entries (ipset_entries , self .module )
687+ if addr_type is None and ipset_entries :
688+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
689+ ipset_options = {}
690+ if addr_type == "ipv6" :
691+ ipset_options = {
692+ "family" : "inet6" ,
693+ }
631694 ipset_exists = ipset in self .fw .config ().getIPSetNames ()
632695 fw_ipset = None
633696 fw_ipset_settings = None
@@ -641,7 +704,9 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
641704 % (ipset , fw_ipset_settings .getType ())
642705 )
643706 elif self .state == "present" :
644- fw_ipset , fw_ipset_settings = self ._create_ipset (ipset , ipset_type )
707+ fw_ipset , fw_ipset_settings = self ._create_ipset (
708+ ipset , ipset_type , ipset_options
709+ )
645710 self .changed = True
646711 ipset_exists = True
647712 if self .state == "present" :
@@ -1256,6 +1321,12 @@ def set_service(
12561321 self .change ("--zone" , self .zone , op + item )
12571322
12581323 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
1324+ addr_type = validate_ipset_entries (ipset_entries , self .module )
1325+ if addr_type is None and ipset_entries :
1326+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
1327+ ipset_options = []
1328+ if addr_type == "ipv6" :
1329+ ipset_options = ["--option" , "family=inet6" ]
12591330 present = self .check_state (["present" , "absent" ], "ipset" )
12601331 known_ipsets = self .cmd ("--get-ipsets" ).split ()
12611332 ipset_exists = ipset in known_ipsets
@@ -1280,7 +1351,9 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
12801351 self .module .fail_json (
12811352 msg = "ipset_type needed when creating a new ipset"
12821353 )
1283- self .change ("--new-ipset" , ipset , "--type=%s" % ipset_type )
1354+ self .change (
1355+ "--new-ipset" , ipset , "--type=%s" % ipset_type , * ipset_options
1356+ )
12841357
12851358 existing_description = self .cmd ("--ipset" , ipset , "--get-description" )
12861359 if description is not None and description != existing_description :
@@ -1635,6 +1708,10 @@ def get_forward_port(module):
16351708def parse_forward_port (module , item ):
16361709 type_string = "forward_port"
16371710
1711+ _port = None
1712+ _protocol = None
1713+ _to_port = None
1714+ _to_addr = None
16381715 if isinstance (item , dict ):
16391716 if "port" not in item :
16401717 module .fail_json (
0 commit comments