2828 - Name of a port or port range to add/remove to/from firewalld.
2929 - Must be in the form PORT/PROTOCOL or PORT-PORT/PROTOCOL for port ranges.
3030 type: str
31+ source_port:
32+ description:
33+ - Name of a source port or port range to add/remove to/from firewalld.
34+ - Must be in the form PORT/PROTOCOL or PORT-PORT/PROTOCOL for port ranges.
35+ type: str
3136 port_forward:
3237 description:
3338 - Port and protocol to forward using firewalld.
185190 permanent: true
186191 state: enabled
187192
193+ - name: Permit traffic in home zone from port 20561/udp
194+ ansible.posix.firewalld:
195+ source_port: 20561/udp
196+ zone: home
197+ permanent: true
198+ state: enabled
199+
188200- name: Permit traffic in dmz zone on http service
189201 ansible.posix.firewalld:
190202 zone: dmz
@@ -552,6 +564,43 @@ def set_disabled_permanent(self, port, protocol, timeout):
552564 self .update_fw_settings (fw_zone , fw_settings )
553565
554566
567+ class SourcePortTransaction (FirewallTransaction ):
568+ """
569+ SourcePortTransaction
570+ """
571+
572+ def __init__ (self , module , action_args = None , zone = None , desired_state = None , permanent = False , immediate = False ):
573+ super (SourcePortTransaction , self ).__init__ (
574+ module , action_args = action_args , desired_state = desired_state , zone = zone , permanent = permanent , immediate = immediate
575+ )
576+
577+ def get_enabled_immediate (self , port , protocol , timeout ):
578+ if self .fw_offline :
579+ dummy , fw_settings = self .get_fw_zone_settings ()
580+ return fw_settings .querySourcePort (port = port , protocol = protocol )
581+ return self .fw .querySourcePort (zone = self .zone , port = port , protocol = protocol )
582+
583+ def get_enabled_permanent (self , port , protocol , timeout ):
584+ dummy , fw_settings = self .get_fw_zone_settings ()
585+ return fw_settings .querySourcePort (port = port , protocol = protocol )
586+
587+ def set_enabled_immediate (self , port , protocol , timeout ):
588+ self .fw .addSourcePort (zone = self .zone , port = port , protocol = protocol , timeout = timeout )
589+
590+ def set_enabled_permanent (self , port , protocol , timeout ):
591+ fw_zone , fw_settings = self .get_fw_zone_settings ()
592+ fw_settings .addSourcePort (port = port , protocol = protocol )
593+ self .update_fw_settings (fw_zone , fw_settings )
594+
595+ def set_disabled_immediate (self , port , protocol , timeout ):
596+ self .fw .removeSourcePort (zone = self .zone , port = port , protocol = protocol )
597+
598+ def set_disabled_permanent (self , port , protocol , timeout ):
599+ fw_zone , fw_settings = self .get_fw_zone_settings ()
600+ fw_settings .removeSourcePort (port = port , protocol = protocol )
601+ self .update_fw_settings (fw_zone , fw_settings )
602+
603+
555604class InterfaceTransaction (FirewallTransaction ):
556605 """
557606 InterfaceTransaction
@@ -879,6 +928,7 @@ def main():
879928 service = dict (type = 'str' ),
880929 protocol = dict (type = 'str' ),
881930 port = dict (type = 'str' ),
931+ source_port = dict (type = 'str' ),
882932 port_forward = dict (type = 'list' , elements = 'dict' ),
883933 rich_rule = dict (type = 'str' ),
884934 zone = dict (type = 'str' ),
@@ -900,8 +950,8 @@ def main():
900950 source = ('permanent' ,),
901951 ),
902952 mutually_exclusive = [
903- ['icmp_block' , 'icmp_block_inversion' , 'service' , 'protocol' , 'port' , 'port_forward ' , 'rich_rule ' ,
904- 'interface' , 'forward' , 'masquerade' , 'source' , 'target' ]
953+ ['icmp_block' , 'icmp_block_inversion' , 'service' , 'protocol' , 'port' , 'source_port ' , 'port_forward ' ,
954+ 'rich_rule' , ' interface' , 'forward' , 'masquerade' , 'source' , 'target' ]
905955 ],
906956 )
907957
@@ -957,6 +1007,17 @@ def main():
9571007 else :
9581008 port_protocol = None
9591009
1010+ source_port = None
1011+ if module .params ['source_port' ] is not None :
1012+ if '/' in module .params ['source_port' ]:
1013+ source_port , source_port_protocol = module .params ['source_port' ].strip ().split ('/' )
1014+ else :
1015+ source_port_protocol = None
1016+ if not source_port_protocol :
1017+ module .fail_json (msg = 'improper source_port format (missing protocol?)' )
1018+ else :
1019+ source_port_protocol = None
1020+
9601021 port_forward_toaddr = ''
9611022 port_forward = None
9621023 if module .params ['port_forward' ] is not None :
@@ -973,7 +1034,7 @@ def main():
9731034 port_forward_toaddr = port_forward ['toaddr' ]
9741035
9751036 modification = False
976- if any ([icmp_block , icmp_block_inversion , service , protocol , port , port_forward , rich_rule ,
1037+ if any ([icmp_block , icmp_block_inversion , service , protocol , port , source_port , port_forward , rich_rule ,
9771038 interface , forward , masquerade , source , target ]):
9781039 modification = True
9791040 if modification and desired_state in ['absent' , 'present' ] and target is None :
@@ -1079,6 +1140,26 @@ def main():
10791140 )
10801141 )
10811142
1143+ if source_port is not None :
1144+
1145+ transaction = SourcePortTransaction (
1146+ module ,
1147+ action_args = (source_port , source_port_protocol , timeout ),
1148+ zone = zone ,
1149+ desired_state = desired_state ,
1150+ permanent = permanent ,
1151+ immediate = immediate ,
1152+ )
1153+
1154+ changed , transaction_msgs = transaction .run ()
1155+ msgs = msgs + transaction_msgs
1156+ if changed is True :
1157+ msgs .append (
1158+ "Changed source_port %s to %s" % (
1159+ "%s/%s" % (source_port , source_port_protocol ), desired_state
1160+ )
1161+ )
1162+
10821163 if port_forward is not None :
10831164 transaction = ForwardPortTransaction (
10841165 module ,
0 commit comments