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
280280"""
281281
282282from ansible .module_utils .basic import AnsibleModule
283+ from ansible .module_utils .six import string_types
283284import re
284285import os
285286
287+ try :
288+ import ipaddress
289+
290+ HAS_IPADDRESS = True
291+ except ImportError :
292+ HAS_IPADDRESS = False
293+
294+ try :
295+ from firewall .functions import check_mac
296+
297+ HAS_CHECK_MAC = True
298+ except ImportError :
299+ HAS_CHECK_MAC = False
300+
301+ def check_mac (mac ):
302+ return False
303+
304+
286305try :
287306 import firewall .config
288307
315334 NM_IMPORTED = False
316335
317336
337+ # The argument to ip_interface must be a unicode string
338+ # Must be "cast" in python2, python3 does not need this
339+ def ip_interface (entry ):
340+ try :
341+ entry_str = unicode (entry )
342+ except NameError : # unicode is not defined in python3
343+ entry_str = entry
344+ return ipaddress .ip_interface (entry_str )
345+
346+
318347def try_get_connection_of_interface (interface ):
319348 try :
320349 return nm_get_connection_of_interface (interface )
@@ -343,6 +372,42 @@ def try_set_zone_of_interface(module, _zone, interface):
343372 return (False , False )
344373
345374
375+ # Check that all of the ipset entries are ipv4, ipv6, or mac addresses
376+ # if not, fail the module
377+ # if they are, return "ipv4", "ipv6", or "mac"
378+ def get_ipset_entries_type (ipset_entries , module ):
379+ addr_type = None
380+ is_mixed_addr_types = False
381+ for entry in ipset_entries :
382+ if check_mac (entry ):
383+ if addr_type is None :
384+ addr_type = "mac"
385+ elif addr_type != "mac" :
386+ is_mixed_addr_types = True
387+ else :
388+ if HAS_IPADDRESS :
389+ addr = ip_interface (entry )
390+ else :
391+ module .fail_json (msg = "No IP address library found" )
392+ if addr .version == 4 :
393+ if addr_type is None :
394+ addr_type = "ipv4"
395+ elif addr_type != "ipv4" :
396+ is_mixed_addr_types = True
397+ elif addr .version == 6 :
398+ if addr_type is None :
399+ addr_type = "ipv6"
400+ elif addr_type != "ipv6" :
401+ is_mixed_addr_types = True
402+ else :
403+ module .fail_json (msg = "Invalid IP address - " + entry )
404+ if is_mixed_addr_types :
405+ module .fail_json (
406+ msg = "Address types cannot be mixed in ipset entries - " + str (ipset_entries )
407+ )
408+ return addr_type
409+
410+
346411# Above: adapted from firewall-cmd source code
347412
348413
@@ -613,13 +678,14 @@ def set_service(
613678 else :
614679 self .module .fail_json (msg = "INVALID SERVICE - " + item )
615680
616- def _create_ipset (self , ipset , ipset_type ):
681+ def _create_ipset (self , ipset , ipset_type , ipset_options ):
617682 if not ipset_type :
618683 self .module .fail_json (msg = "ipset_type needed when creating a new ipset" )
619684
620685 fw_ipset = None
621686 fw_ipset_settings = FirewallClientIPSetSettings ()
622687 fw_ipset_settings .setType (ipset_type )
688+ fw_ipset_settings .setOptions (ipset_options )
623689 if not self .module .check_mode :
624690 self .fw .config ().addIPSet (ipset , fw_ipset_settings )
625691 fw_ipset = self .fw .config ().getIPSetByName (ipset )
@@ -628,6 +694,14 @@ def _create_ipset(self, ipset, ipset_type):
628694 return fw_ipset , fw_ipset_settings
629695
630696 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
697+ addr_type = get_ipset_entries_type (ipset_entries , self .module )
698+ if addr_type is None and ipset_entries :
699+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
700+ ipset_options = {}
701+ if addr_type == "ipv6" :
702+ ipset_options = {
703+ "family" : "inet6" ,
704+ }
631705 ipset_exists = ipset in self .fw .config ().getIPSetNames ()
632706 fw_ipset = None
633707 fw_ipset_settings = None
@@ -641,7 +715,9 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
641715 % (ipset , fw_ipset_settings .getType ())
642716 )
643717 elif self .state == "present" :
644- fw_ipset , fw_ipset_settings = self ._create_ipset (ipset , ipset_type )
718+ fw_ipset , fw_ipset_settings = self ._create_ipset (
719+ ipset , ipset_type , ipset_options
720+ )
645721 self .changed = True
646722 ipset_exists = True
647723 if self .state == "present" :
@@ -1256,6 +1332,12 @@ def set_service(
12561332 self .change ("--zone" , self .zone , op + item )
12571333
12581334 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
1335+ addr_type = get_ipset_entries_type (ipset_entries , self .module )
1336+ if addr_type is None and ipset_entries :
1337+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
1338+ ipset_options = []
1339+ if addr_type == "ipv6" :
1340+ ipset_options = ["--option" , "family=inet6" ]
12591341 present = self .check_state (["present" , "absent" ], "ipset" )
12601342 known_ipsets = self .cmd ("--get-ipsets" ).split ()
12611343 ipset_exists = ipset in known_ipsets
@@ -1280,7 +1362,9 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
12801362 self .module .fail_json (
12811363 msg = "ipset_type needed when creating a new ipset"
12821364 )
1283- self .change ("--new-ipset" , ipset , "--type=%s" % ipset_type )
1365+ self .change (
1366+ "--new-ipset" , ipset , "--type=%s" % ipset_type , * ipset_options
1367+ )
12841368
12851369 existing_description = self .cmd ("--ipset" , ipset , "--get-description" )
12861370 if description is not None and description != existing_description :
@@ -1635,6 +1719,10 @@ def get_forward_port(module):
16351719def parse_forward_port (module , item ):
16361720 type_string = "forward_port"
16371721
1722+ _port = None
1723+ _protocol = None
1724+ _to_port = None
1725+ _to_addr = None
16381726 if isinstance (item , dict ):
16391727 if "port" not in item :
16401728 module .fail_json (
@@ -1653,7 +1741,7 @@ def parse_forward_port(module, item):
16531741 else :
16541742 _to_port = None
16551743 _to_addr = item .get ("toaddr" )
1656- elif isinstance (item , str ):
1744+ elif isinstance (item , string_types ):
16571745 args = item .split (";" )
16581746 if len (args ) == 3 :
16591747 __port , _to_port , _to_addr = args
0 commit comments