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
@@ -343,6 +362,42 @@ def try_set_zone_of_interface(module, _zone, interface):
343362 return (False , False )
344363
345364
365+ # Check that all of the ipset entries are ipv4, ipv6, or mac addresses
366+ # if not, fail the module
367+ # if they are, return "ipv4", "ipv6", or "mac"
368+ def validate_ipset_entries (ipset_entries , module ):
369+ addr_type = None
370+ is_mixed_addr_types = False
371+ for entry in ipset_entries :
372+ if check_mac (entry ):
373+ if addr_type is None :
374+ addr_type = "mac"
375+ elif addr_type != "mac" :
376+ is_mixed_addr_types = True
377+ else :
378+ if HAS_IPADDRESS :
379+ addr = ipaddress .ip_interface (entry )
380+ else :
381+ module .fail_json (msg = "No IP address library found" )
382+ if addr .version == 4 :
383+ if addr_type is None :
384+ addr_type = "ipv4"
385+ elif addr_type != "ipv4" :
386+ is_mixed_addr_types = True
387+ elif addr .version == 6 :
388+ if addr_type is None :
389+ addr_type = "ipv6"
390+ elif addr_type != "ipv6" :
391+ is_mixed_addr_types = True
392+ else :
393+ module .fail_json (msg = "Invalid IP address - " + entry )
394+ if is_mixed_addr_types :
395+ module .fail_json (
396+ msg = "Address types cannot be mixed in ipset entries - " + str (ipset_entries )
397+ )
398+ return addr_type
399+
400+
346401# Above: adapted from firewall-cmd source code
347402
348403
@@ -613,13 +668,14 @@ def set_service(
613668 else :
614669 self .module .fail_json (msg = "INVALID SERVICE - " + item )
615670
616- def _create_ipset (self , ipset , ipset_type ):
671+ def _create_ipset (self , ipset , ipset_type , ipset_options ):
617672 if not ipset_type :
618673 self .module .fail_json (msg = "ipset_type needed when creating a new ipset" )
619674
620675 fw_ipset = None
621676 fw_ipset_settings = FirewallClientIPSetSettings ()
622677 fw_ipset_settings .setType (ipset_type )
678+ fw_ipset_settings .setOptions (ipset_options )
623679 if not self .module .check_mode :
624680 self .fw .config ().addIPSet (ipset , fw_ipset_settings )
625681 fw_ipset = self .fw .config ().getIPSetByName (ipset )
@@ -628,6 +684,14 @@ def _create_ipset(self, ipset, ipset_type):
628684 return fw_ipset , fw_ipset_settings
629685
630686 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
687+ addr_type = validate_ipset_entries (ipset_entries , self .module )
688+ if addr_type is None and ipset_entries :
689+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
690+ ipset_options = {}
691+ if addr_type == "ipv6" :
692+ ipset_options = {
693+ "family" : "inet6" ,
694+ }
631695 ipset_exists = ipset in self .fw .config ().getIPSetNames ()
632696 fw_ipset = None
633697 fw_ipset_settings = None
@@ -641,7 +705,9 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
641705 % (ipset , fw_ipset_settings .getType ())
642706 )
643707 elif self .state == "present" :
644- fw_ipset , fw_ipset_settings = self ._create_ipset (ipset , ipset_type )
708+ fw_ipset , fw_ipset_settings = self ._create_ipset (
709+ ipset , ipset_type , ipset_options
710+ )
645711 self .changed = True
646712 ipset_exists = True
647713 if self .state == "present" :
@@ -1256,6 +1322,12 @@ def set_service(
12561322 self .change ("--zone" , self .zone , op + item )
12571323
12581324 def set_ipset (self , ipset , description , short , ipset_type , ipset_entries ):
1325+ addr_type = validate_ipset_entries (ipset_entries , self .module )
1326+ if addr_type is None and ipset_entries :
1327+ self .module .fail_json (msg = "Invalid IP address - " + str (ipset_entries ))
1328+ ipset_options = []
1329+ if addr_type == "ipv6" :
1330+ ipset_options = ["--option" , "family=inet6" ]
12591331 present = self .check_state (["present" , "absent" ], "ipset" )
12601332 known_ipsets = self .cmd ("--get-ipsets" ).split ()
12611333 ipset_exists = ipset in known_ipsets
@@ -1280,7 +1352,9 @@ def set_ipset(self, ipset, description, short, ipset_type, ipset_entries):
12801352 self .module .fail_json (
12811353 msg = "ipset_type needed when creating a new ipset"
12821354 )
1283- self .change ("--new-ipset" , ipset , "--type=%s" % ipset_type )
1355+ self .change (
1356+ "--new-ipset" , ipset , "--type=%s" % ipset_type , * ipset_options
1357+ )
12841358
12851359 existing_description = self .cmd ("--ipset" , ipset , "--get-description" )
12861360 if description is not None and description != existing_description :
@@ -1635,6 +1709,10 @@ def get_forward_port(module):
16351709def parse_forward_port (module , item ):
16361710 type_string = "forward_port"
16371711
1712+ _port = None
1713+ _protocol = None
1714+ _to_port = None
1715+ _to_addr = None
16381716 if isinstance (item , dict ):
16391717 if "port" not in item :
16401718 module .fail_json (
@@ -1653,7 +1731,7 @@ def parse_forward_port(module, item):
16531731 else :
16541732 _to_port = None
16551733 _to_addr = item .get ("toaddr" )
1656- elif isinstance (item , str ):
1734+ elif isinstance (item , string_types ):
16571735 args = item .split (";" )
16581736 if len (args ) == 3 :
16591737 __port , _to_port , _to_addr = args
0 commit comments