async fn dhcp_server_config_to_option_and_param(
        &self,
        pid: PortId,
        config: &lifmgr::DhcpServerConfig,
    ) -> error::Result<(Vec<fnetdhcp::Option_>, Vec<fnetdhcp::Parameter>, Option<bool>)> {
        let mut options = Vec::new();
        let mut params = Vec::new();

        let lifmgr::DhcpServerConfig {
            options:
                lifmgr::DhcpServerOptions { id: _, default_gateway, dns_server, enable, lease_time_sec },
            pool,
            reservations,
        } = config;

        if let Some(default_gateway) = default_gateway {
            options.push(fnetdhcp::Option_::Router(vec![*default_gateway]));
        }

        if let Some(dns_server) = dns_server {
            options.push(fnetdhcp::Option_::DomainNameServer(
                dns_server
                    .servers
                    .iter()
                    .filter_map(|addr| match addr.address {
                        IpAddr::V4(addr) => Some(fnet::Ipv4Address { addr: addr.octets() }),
                        IpAddr::V6(_) => None,
                    })
                    .collect(),
            ));
        }

        if let Some(lease_time_sec) = lease_time_sec {
            params.push(fnetdhcp::Parameter::Lease(fnetdhcp::LeaseLength {
                default: Some(*lease_time_sec),
                max: None,
                ..fnetdhcp::LeaseLength::EMPTY
            }));
        }

        if let Some(DhcpAddressPool { start, end, .. }) = pool {
            // NOTE: network and mask are not specified in the input configuration, so use the
            // first address from the interface.
            let (addr, prefix_len) = self
                .get_interface(pid)
                .await?
                .addresses
                .into_iter()
                .find_map(
                    |fnet_interfaces_ext::Address {
                         addr: fnet::Subnet { addr, prefix_len },
                         valid_until: _,
                     }| {
                        match addr {
                            fnet::IpAddress::Ipv4(fnet::Ipv4Address { addr }) => {
                                Some((addr, prefix_len))
                            }
                            fnet::IpAddress::Ipv6(_) => None,
                        }
                    },
                )
                .ok_or_else(|| {
                    warn!("can't add address pool: no address found on interface {:?}", pid);
                    error::NetworkManager::Hal(error::Hal::OperationFailed)
                })?;

            let subnet = net_types::ip::AddrSubnet::<_, net_types::SpecifiedAddr<_>>::new(
                net_types::ip::Ipv4Addr::new(addr),
                prefix_len,
            )
            .map_err(|e| {
                warn!("can't get subnet from interface address: {:?}", e);
                error::NetworkManager::Hal(error::Hal::OperationFailed)
            })?
            .into_subnet();

            for addr in &[start, end] {
                if !subnet.contains(&net_types::ip::Ipv4Addr::new(addr.octets())) {
                    warn!(
                        "address pool range {}-{}, does not match subnet {} of interface {:?}",
                        start, end, subnet, pid
                    );
                    return Err(error::NetworkManager::Hal(error::Hal::OperationFailed));
                }
            }

            params.push(fnetdhcp::Parameter::AddressPool(fnetdhcp::AddressPool {
                prefix_length: Some(subnet.prefix()),
                range_start: Some(fnet::Ipv4Address { addr: start.octets() }),
                range_stop: Some(fnet::Ipv4Address { addr: end.octets() }),
                ..fnetdhcp::AddressPool::EMPTY
            }));
        }

        params.push(fnetdhcp::Parameter::StaticallyAssignedAddrs(
            reservations
                .iter()
                .map(|reservation| fnetdhcp::StaticAssignment {
                    host: Some(fnet::MacAddress { octets: reservation.mac.to_array() }),
                    assigned_addr: Some(fnet::Ipv4Address { addr: reservation.address.octets() }),
                    ..fnetdhcp::StaticAssignment::EMPTY
                })
                .collect(),
        ));

        Ok((options, params, *enable))
    }
/// Validates and extracts DHCP server options, parameters and the desired enable state from
/// input configuration.
///
/// # Errors
///
/// Returns an error if the input configuration is invalid.
Validates and extracts DHCP server options, parameters and the desired enable state from
input configuration.
Validates and extracts DHCP server options parameters and the desired enable state from input configuration .
async fn dhcp_server_config_to_option_and_param(
        &self,
        pid: PortId,
        config: &lifmgr::DhcpServerConfig,
    ) -> error::Result<(Vec<fnetdhcp::Option_>, Vec<fnetdhcp::Parameter>, Option<bool>)> {
        let mut options = Vec::new();
        let mut params = Vec::new();
        let lifmgr::DhcpServerConfig {
            options:
                lifmgr::DhcpServerOptions { id: _, default_gateway, dns_server, enable, lease_time_sec },
            pool,
            reservations,
        } = config;
        if let Some(default_gateway) = default_gateway {
            options.push(fnetdhcp::Option_::Router(vec![*default_gateway]));
        }
        if let Some(dns_server) = dns_server {
            options.push(fnetdhcp::Option_::DomainNameServer(
                dns_server
                    .servers
                    .iter()
                    .filter_map(|addr| match addr.address {
                        IpAddr::V4(addr) => Some(fnet::Ipv4Address { addr: addr.octets() }),
                        IpAddr::V6(_) => None,
                    })
                    .collect(),
            ));
        }
        if let Some(lease_time_sec) = lease_time_sec {
            params.push(fnetdhcp::Parameter::Lease(fnetdhcp::LeaseLength {
                default: Some(*lease_time_sec),
                max: None,
                ..fnetdhcp::LeaseLength::EMPTY
            }));
        }
        if let Some(DhcpAddressPool { start, end, .. }) = pool {
            // NOTE: network and mask are not specified in the input configuration, so use the
            // first address from the interface.
            let (addr, prefix_len) = self
                .get_interface(pid)
                .await?
                .addresses
                .into_iter()
                .find_map(
                    |fnet_interfaces_ext::Address {
                         addr: fnet::Subnet { addr, prefix_len },
                         valid_until: _,
                     }| {
                        match addr {
                            fnet::IpAddress::Ipv4(fnet::Ipv4Address { addr }) => {
                                Some((addr, prefix_len))
                            }
                            fnet::IpAddress::Ipv6(_) => None,
                        }
                    },
                )
                .ok_or_else(|| {
                    warn!("can't add address pool: no address found on interface {:?}", pid);
                    error::NetworkManager::Hal(error::Hal::OperationFailed)
                })?;
            let subnet = net_types::ip::AddrSubnet::<_, net_types::SpecifiedAddr<_>>::new(
                net_types::ip::Ipv4Addr::new(addr),
                prefix_len,
            )
            .map_err(|e| {
                warn!("can't get subnet from interface address: {:?}", e);
                error::NetworkManager::Hal(error::Hal::OperationFailed)
            })?
            .into_subnet();
            for addr in &[start, end] {
                if !subnet.contains(&net_types::ip::Ipv4Addr::new(addr.octets())) {
                    warn!(
                        "address pool range {}-{}, does not match subnet {} of interface {:?}",
                        start, end, subnet, pid
                    );
                    return Err(error::NetworkManager::Hal(error::Hal::OperationFailed));
                }
            }
            params.push(fnetdhcp::Parameter::AddressPool(fnetdhcp::AddressPool {
                prefix_length: Some(subnet.prefix()),
                range_start: Some(fnet::Ipv4Address { addr: start.octets() }),
                range_stop: Some(fnet::Ipv4Address { addr: end.octets() }),
                ..fnetdhcp::AddressPool::EMPTY
            }));
        }
        params.push(fnetdhcp::Parameter::StaticallyAssignedAddrs(
            reservations
                .iter()
                .map(|reservation| fnetdhcp::StaticAssignment {
                    host: Some(fnet::MacAddress { octets: reservation.mac.to_array() }),
                    assigned_addr: Some(fnet::Ipv4Address { addr: reservation.address.octets() }),
                    ..fnetdhcp::StaticAssignment::EMPTY
                })
                .collect(),
        ));
        Ok((options, params, *enable))
    }
async fn dhcp_server_config_to_option_and_param ( & self , pid : PortId , config : & lifmgr :: DhcpServerConfig , ) -> error :: Result < ( Vec < fnetdhcp :: Option_ > , Vec < fnetdhcp :: Parameter > , Option < bool > ) > { let mut options = Vec :: new ( ) ; let mut params = Vec :: new ( ) ; let lifmgr :: DhcpServerConfig { options : lifmgr :: DhcpServerOptions { id : _ , default_gateway , dns_server , enable , lease_time_sec } , pool , reservations , } = config ; if let Some ( default_gateway ) = default_gateway { options . push ( fnetdhcp :: Option_ :: Router ( vec ! [ default_gateway ] ) ) ; } if let Some ( dns_server ) = dns_server { options . push ( fnetdhcp :: Option_ :: DomainNameServer ( dns_server . servers . iter ( ) . filter_map ( | addr | match addr . address { IpAddr :: V4 ( addr ) => Some ( fnet :: Ipv4Address { addr : addr . octets ( ) } ) , IpAddr :: V6 ( _ ) => None , } ) . collect ( ) , ) ) ; } if let Some ( lease_time_sec ) = lease_time_sec { params . push ( fnetdhcp :: Parameter :: Lease ( fnetdhcp :: LeaseLength { default : Some ( * lease_time_sec ) , max : None , .. fnetdhcp :: LeaseLength :: EMPTY } ) ) ; } if let Some ( DhcpAddressPool { start , end , .. } ) = pool { // NOTE: network and mask are not specified in the input configuration, so use the // first address from the interface. let ( addr , prefix_len ) = self . get_interface ( pid ) . await ? . addresses . into_iter ( ) . find_map ( | fnet_interfaces_ext :: Address { addr : fnet :: Subnet { addr , prefix_len } , valid_until : _ , } | { match addr { fnet :: IpAddress :: Ipv4 ( fnet :: Ipv4Address { addr } ) => { Some ( ( addr , prefix_len ) ) } fnet :: IpAddress :: Ipv6 ( _ ) => None , } } , ) . ok_or_else ( | | { warn ! ( " " pid ) ; error :: NetworkManager :: Hal ( error :: Hal :: OperationFailed ) } ) ? ; let subnet = net_types :: ip :: AddrSubnet :: < _ , net_types :: SpecifiedAddr < _ > > :: new ( net_types :: ip :: Ipv4Addr :: new ( addr ) , prefix_len , ) . map_err ( | e | { warn ! ( " " e ) ; error :: NetworkManager :: Hal ( error :: Hal :: OperationFailed ) } ) ? . into_subnet ( ) ; for addr in & [ start , end ] { if ! subnet . contains ( & net_types :: ip :: Ipv4Addr :: new ( addr . octets ( ) ) ) { warn ! ( " " start end subnet pid ) ; return Err ( error :: NetworkManager :: Hal ( error :: Hal :: OperationFailed ) ) ; } } params . push ( fnetdhcp :: Parameter :: AddressPool ( fnetdhcp :: AddressPool { prefix_length : Some ( subnet . prefix ( ) ) , range_start : Some ( fnet :: Ipv4Address { addr : start . octets ( ) } ) , range_stop : Some ( fnet :: Ipv4Address { addr : end . octets ( ) } ) , .. fnetdhcp :: AddressPool :: EMPTY } ) ) ; } params . push ( fnetdhcp :: Parameter :: StaticallyAssignedAddrs ( reservations . iter ( ) . map ( | reservation | fnetdhcp :: StaticAssignment { host : Some ( fnet :: MacAddress { octets : reservation . mac . to_array ( ) } ) , assigned_addr : Some ( fnet :: Ipv4Address { addr : reservation . address . octets ( ) } ) , .. fnetdhcp :: StaticAssignment :: EMPTY } ) . collect ( ) , ) ) ; Ok ( ( options , params , * enable ) ) }
Validates and extracts DHCP server options, parameters and the desired enable state from
input configuration.
Validates and extracts DHCP server options parameters and the desired enable state from input configuration .
&self
pid
PortId
config
&lifmgr::DhcpServerConfig
&self
pid
PortId
config
&lifmgr::DhcpServerConfig
errors
Returns an error if the input configuration is invalid.
Returns an error if the input configuration is invalid .