(rule: &INetFwRule, desired: &FirewallRule, existing_protocol: Option<i32>)
| 293 | } |
| 294 | |
| 295 | fn apply_rule_properties(rule: &INetFwRule, desired: &FirewallRule, existing_protocol: Option<i32>) -> Result<(), FirewallError> { |
| 296 | let name = desired.selector_name().unwrap_or("<unknown>"); |
| 297 | let err = map_update_err(name); |
| 298 | |
| 299 | if let Some(protocol) = desired.protocol { |
| 300 | validate_protocol(protocol)?; |
| 301 | } |
| 302 | |
| 303 | // Determine the effective protocol: the desired value if provided, otherwise |
| 304 | // the existing rule's protocol (if updating an existing rule). |
| 305 | let effective_protocol = desired.protocol.or(existing_protocol); |
| 306 | |
| 307 | // If effective_protocol is None, read the current protocol from the rule. |
| 308 | let effective_protocol = match effective_protocol { |
| 309 | Some(protocol) => Some(protocol), |
| 310 | None => Some(unsafe { rule.Protocol() }.map_err(&err)?), |
| 311 | }; |
| 312 | |
| 313 | // Reject port specifications for protocols that don't support them (e.g. ICMP). |
| 314 | // This must be checked regardless of whether the protocol itself was changed, |
| 315 | // because the caller may only be setting local_ports or remote_ports. |
| 316 | if let Some(protocol) = effective_protocol |
| 317 | && !protocol_supports_ports(protocol) |
| 318 | && (desired.local_ports.is_some() || desired.remote_ports.is_some()) { |
| 319 | return Err(t!("firewall.portsNotAllowed", name = name, protocol = protocol).to_string().into()); |
| 320 | } |
| 321 | |
| 322 | if let Some(protocol) = desired.protocol { |
| 323 | if let Some(current_protocol) = existing_protocol |
| 324 | && current_protocol != protocol && !protocol_supports_ports(protocol) { |
| 325 | if desired.local_ports.is_none() { |
| 326 | unsafe { rule.SetLocalPorts(&BSTR::from("")) }.map_err(&err)?; |
| 327 | } |
| 328 | if desired.remote_ports.is_none() { |
| 329 | unsafe { rule.SetRemotePorts(&BSTR::from("")) }.map_err(&err)?; |
| 330 | } |
| 331 | } |
| 332 | unsafe { rule.SetProtocol(protocol) }.map_err(&err)?; |
| 333 | } |
| 334 | |
| 335 | if let Some(description) = desired.description.as_ref() { |
| 336 | unsafe { rule.SetDescription(&BSTR::from(description.as_str())) }.map_err(&err)?; |
| 337 | } |
| 338 | if let Some(application_name) = desired.application_name.as_ref() { |
| 339 | unsafe { rule.SetApplicationName(&BSTR::from(application_name.as_str())) }.map_err(&err)?; |
| 340 | } |
| 341 | if let Some(service_name) = desired.service_name.as_ref() { |
| 342 | unsafe { rule.SetServiceName(&BSTR::from(service_name.as_str())) }.map_err(&err)?; |
| 343 | } |
| 344 | if let Some(local_ports) = desired.local_ports.as_ref() { |
| 345 | unsafe { rule.SetLocalPorts(&BSTR::from(local_ports.as_str())) }.map_err(&err)?; |
| 346 | } |
| 347 | if let Some(remote_ports) = desired.remote_ports.as_ref() { |
| 348 | unsafe { rule.SetRemotePorts(&BSTR::from(remote_ports.as_str())) }.map_err(&err)?; |
| 349 | } |
| 350 | if let Some(local_addresses) = desired.local_addresses.as_ref() { |
| 351 | unsafe { rule.SetLocalAddresses(&BSTR::from(local_addresses.as_str())) }.map_err(&err)?; |
| 352 | } |
no test coverage detected