HEX
Server: LiteSpeed
System: Linux s787.bom1.mysecurecloudhost.com 4.18.0-477.13.1.lve.el8.x86_64 #1 SMP Thu Jun 1 16:40:47 EDT 2023 x86_64
User: mobilech (5348)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/__pycache__/win_ip.cpython-310.pyc
o

;j���@s>dZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
mZe�e
�ZdZdd�Zdd�Zd0d	d
�Zdd�Zd
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd1dd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd0d&d'�Z d0d(d)�Z!																						d2d*d+�Z"d,d-�Z#d3d.d/�Z$dS)4z1
The networking module for Windows based systems
�N)�CommandExecutionError�SaltInvocationError�ipcCs0tjj��sdStjjjsdStjjjsdStS)z0
    Confine this module to Windows systems
    )Fz(Module win_ip: Only available on Windows)Fz9Module win_ip: Requires pythonnet (pip install pythonnet))FzIModule win_ip: Requires the PowerShell SDK (System.Management.Automation))�salt�utils�platformZ
is_windows�win_pwshZHAS_CLRZHAS_PWSH_SDK�__virtualname__�r
r
�G/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/win_ip.py�__virtual__s

rcCs,dD]}|�|�}t|t�r|g||<q|S)a~
    Ensure ``ipv4_gateways`` and ``ipv6_gateways`` are always lists.

    PowerShell 5.1's ``ConvertTo-Json`` unwraps single-element arrays to plain
    objects, so a single gateway arrives as a ``dict`` rather than a
    ``list[dict]``. This normalizes the parsed data in-place so callers always
    receive a consistent list type regardless of how many gateways are present.
    )�
ipv4_gateways�
ipv6_gateways)�get�
isinstance�dict)�data�key�valr
r
r�_normalize_gateway_fields&s	


�rc
Cs�|rt|�}ntdd�}i}|��D]�\}}|d}|dr dnd|d|dr*dnd	d
�||<g||d<t|dt�rD|dg|d<|dD]}t�|�}||d�|�|j	�t|j
�t|j�d
��qH|dr}t|dt�rx|dg}n|d}nd	g}|dr�t|dt�r�|dg}n|d}nd	g}|r�|||d<|||d<n|||d<|||d<dd�|dD�}	|	r�|	dd||d<|	dd||d<q|S)z�
    Returns interface data using the legacy netsh-style key names to avoid
    breaking existing scripts. The data is sourced from PowerShell objects,
    not netsh, so it is locale-independent.
    T)�full�	ipv4_dhcp�YesZNo�ipv4_metric�dns_registerzPrimary only�None)�DHCP enabledZInterfaceMetriczRegister with which suffixZip_addrs�ipv4_address)z
IP AddressZNetmaskZSubnet�ipv4_dns�	ipv4_winsz#DNS servers configured through DHCPz$WINS servers configured through DHCPz!Statically Configured DNS Serversz"Statically Configured WINS ServerscS�g|]	}|�d�r|�qS�r�r��.0�gr
r
r�
<listcomp>r�z1_get_interfaces_legacy_format.<locals>.<listcomp>r
rr�Default Gateway�metriczGateway Metric)�get_interface_new�list_interfaces�itemsr�str�	ipaddress�
IPv4Interface�append�_string_from_ip_int�_ip�netmask�network)
�nameZ
interfaces�legacyrZis_dhcp�addrZip_infoZ	dns_valueZ
wins_value�gwsr
r
r�_get_interfaces_legacy_format6sT


�

��	

�r9cCsgd�}td|dd�S)a#
    Return raw configs for all interfaces as returned by netsh. This command is
    localized and will return different text depending on the locality of the
    operating system.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.raw_interface_configs
    )ZnetshZ	interfacerZshowZconfigzcmd.runF)Zpython_shell)Z__salt__)�cmdr
r
r�raw_interface_configszsr;cCst�S)a�
    Return IP configuration for all network interfaces using the legacy
    ``netsh``-compatible data format.

    Each interface is keyed by its alias and contains ``ip_addrs``,
    ``ipv4_gateway``, ``dns_servers``, and related fields mirroring the
    structure formerly produced by ``netsh interface ip show config``.
    Prefer :func:`list_interfaces` with ``full=True`` for richer, always-
    English output.

    Returns:
        dict: A dictionary keyed by interface name.  Each value is a
        dict with the legacy ``netsh``-style fields.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.get_all_interfaces
    �r9r
r
r
r�get_all_interfaces�sr=cCst|�S)z�
    Return the IP configuration of a single network interface

    Args:

        iface (str): The name of the interface

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.get_interface 'Local Area Connection'
    r<��ifacer
r
r�
get_interface�sr@c	C�tjj���}d|�d�}|�|�}Wd�n1swYzt|dur)|nd�}Wnttfy@d|�d�}t|��w|dkrMtd|�d���|dkS)	a
    Returns ``True`` if interface is enabled, otherwise ``False``

    Args:

        iface (str): The name of the interface to manage

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.is_enabled 'Local Area Connection #2'
    �)
            [int](Get-NetAdapter -Name 'zS' `
                            -ErrorAction SilentlyContinue).AdminStatus
        Nr�Interface '� ' not found or invalid response.�' not found��	rrr�PowerShellSession�run�int�
ValueError�	TypeErrorr�r?�sessionr:�status�msgr
r
r�
is_enabled�����rQc	CrA)	a
    Returns ``True`` if interface is disabled, otherwise ``False``

    Args:

        iface (str): The name of the interface to manage

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.is_disabled 'Local Area Connection #2'
    rBzX' `
                                 -ErrorAction SilentlyContinue).AdminStatus
        NrrCrDrE�rGrMr
r
r�is_disabled�rRrTcC�t|dd�dS)z�
    Enable an interface

    Args:

        iface (str): The name of the interface to manage

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.enable 'Local Area Connection #2'
    T��enabledN��
set_interfacer>r
r
r�enable��rZcCrU)z�
    Disable an interface

    Args:

        iface (str): The name of the interface to manage

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.disable 'Local Area Connection #2'
    FrVNrXr>r
r
r�disable
r[r\cCs.tjjj�|�std|�d���tjj�|�S)z�
    Convenience function to convert the netmask to the CIDR subnet length

    Args:

        mask (str): A netmask

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.get_subnet_length 255.255.255.0
    �'z' is not a valid netmask)rr�validate�netr3rr4Zget_net_size)�maskr
r
r�get_subnet_lengthsraFcCshtjjj�|�std|�d���|r"tjjj�|�s"td|�d���d|vr*|d7}d|vr3|�d�n|df\}}tjj���/}t	||�}d|�d�}|�
|�}	|	d	urWd
}
nt|	t�ra||	v}
n||	�
�k}
Wd	�n1sqwY|
r�d|�d|�d�}t|��t|||r�|nd	|d
�t|�|}d|di}
|r�dd�|dD�}|r�|dd|
d<|
S)a�
    Set static IP configuration on a Windows NIC

    Args:

        iface (str):
            The name of the interface to manage

        addr (str):
            IP address with subnet length (ex. ``10.1.2.3/24``). The
            :mod:`ip.get_subnet_length <salt.modules.win_ip.get_subnet_length>`
            function can be used to calculate the subnet length from a netmask.

        gateway (:obj:`str`, optional):
            If specified, the default gateway will be set to this value.
            Default is ``None``.

        append (:obj:`bool`, optional):
            If ``True``, the address will be added as a secondary IP to the
            interface. If ``False``, all existing IPv4 addresses are cleared
            first. Defaults to ``False``.

    Returns:
        dict: A dictionary with the applied settings, e.g.::

            {"Address Info": ["192.168.1.5/24"], "Default Gateway": "192.168.1.1"}

        ``Default Gateway`` is only present when the ``gateway`` argument is
        provided.

    Raises:
        SaltInvocationError: If ``addr`` or ``gateway`` is not a valid IPv4
            address.
        CommandExecutionError: If the address already exists on the interface.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.set_static_ip 'Local Area Connection' 10.1.2.3/24 gateway=10.1.2.1
        salt -G 'os_family:Windows' ip.set_static_ip 'Local Area Connection' 10.1.2.4/24 append=True
    zInvalid address 'r]zInvalid default gateway '�/z/24�24z/
            (Get-NetIPAddress -InterfaceIndex z� `
                              -AddressFamily IPv4 `
                              -ErrorAction SilentlyContinue).IPAddress
        NFz	Address 'z' already exists on ')r?rr
r0zAddress InforcSr r!r"r#r
r
rr&�r'z!set_static_ip.<locals>.<listcomp>r
rrr()rrr^r_Z	ipv4_addrr�splitrrH�get_interface_indexrIr�list�striprrYr*)r?r7�gatewayr0r�_rN�indexr:�result�existsrPZnew_settings�retr8r
r
r�
set_static_ip.sH+
�


��
�rncCs�tjj���%}t||�}d|�d�}|�|�}|dkr$iWd�SWd�n1s.wYt|dd�tjj���%}t||�}d|�d�}|�|�}|dkr`|dd	�Wd�Std
��1sgwYdS)a�
    Set Windows NIC to get IP from DHCP

    Args:

        iface (str):
            The name of the interface to manage

    Returns:
        dict: ``{}`` if DHCP was already enabled, otherwise
        ``{"Interface": <name>, "DHCP enabled": "Yes"}``.

    Raises:
        CommandExecutionError: If DHCP cannot be enabled.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.set_dhcp_ip 'Local Area Connection'
    z6
            [int](Get-NetIPInterface -InterfaceIndex z� `
                                -AddressFamily IPv4 `
                                -ErrorAction SilentlyContinue).Dhcp
        rFNT)rz1
            (Get-NetIPInterface -InterfaceIndex r)�	InterfacerzFailed to enable DHCP)	rrrrHrerIrY�run_jsonr)r?rNrjr:Zdhcp_enabledr
r
r�set_dhcp_ip�s.
�
��
�
�
�rqcGs�|rt|d���dkr|dd�St|d���dkrt|�St|�}tjj����}d|�d�}|�|�}|dur<g}nt	|t�rNd	d
�|�
dd���D�}t|�}t
|�t
|�krciWd�Sd�d
d
�|D��}d|�d|�d�}|�|�d|�d�}|�|�}|dur�g}nt	|t�r�dd
�|�
dd���D�}t
|�t
|�kr�||d�Wd�SWd�td��1s�wYtd��)a�
    Set static DNS configuration on a Windows NIC

    Args:

        iface (str): The name of the interface to manage

        addrs (list):
            One or more DNS servers to be added. To clear the list of DNS
            servers pass an empty list (``[]``). If undefined or ``None`` no
            changes will be made.

    Returns:
        dict: A dictionary containing the new DNS settings

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.set_static_dns 'Local Area Connection' '192.168.1.1'
        salt -G 'os_family:Windows' ip.set_static_dns 'Local Area Connection' '192.168.1.252' '192.168.1.253'
    r�nonez
No Changes�ro�
DNS Serverz[]�9
            (Get-DnsClientServerAddress -InterfaceIndex �� `
                                        -AddressFamily IPv4 `
                                        -ErrorAction SilentlyContinue).ServerAddresses
        NcS�g|]
}|��r|���qSr
�rg�r$�dr
r
rr&����z"set_static_dns.<locals>.<listcomp>�,�
cS�g|]}d|�d��qS�r]r
)r$�ar
r
rr&��8
            Set-DnsClientServerAddress -InterfaceIndex z< `
                                       -ServerAddresses (z
)
        cSrwr
rxryr
r
rr&r{zFailed to set DNS.)r-�lower�set_dhcp_dnsrerrrrHrIr�replace�
splitlinesrf�set�joinr)r?�addrsrjrNr:�current_dnsZ
requested_dnsZdns_strr
r
r�set_static_dns�sZ
�

����
�

��4
�7�7r�cCs�tjj���J}t||�}d|�d�}|�|�}|s"iWd�Sd|�d�}|�|�d|�d�}|�|�}|sF|dd�Wd�SWd�td	��1sSwYtd	��)
a�
    Set DNS source to DHCP on Windows

    Args:

        iface (str): The name of the interface to manage

    Returns:
        dict: ``{}`` if DNS was already set to automatic (no static servers
        configured), otherwise ``{"Interface": <name>, "DNS Server": "DHCP (Empty)"}``.

    Raises:
        CommandExecutionError: If the DNS reset cannot be verified.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.set_dhcp_dns 'Local Area Connection'
    rurvNr�zH `
                                       -ResetServerAddresses
        zX `
                                        -AddressFamily IPv4).ServerAddresses
        zDHCP (Empty)rsz!Failed to set DNS source to DHCP.�rrrrHrerIr)r?rNrjr:r��resr
r
rr�!s2
�
��
�
�!
�$�$r�cCst|�t|�|ddd�S)a�
    Set both IP Address and DNS to DHCP

    Args:

        iface (str): The name of the interface to manage

    Returns:
        dict: ``{"Interface": <name>, "DNS Server": "DHCP", "DHCP enabled": "Yes"}``

    Raises:
        CommandExecutionError: If either the IP or DNS cannot be switched to DHCP.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.set_dhcp_all 'Local Area Connection'
    ZDHCPr)rortr)rqr�r>r
r
r�set_dhcp_all]sr�cCsdtjj���}|rt|�}d|�d�}nd}|�|�}Wd�n1s%wY|s0td��|S)a,
    Get the Default Gateway on Windows.

    Args:

        iface (str, optional):
            The name or alias of the interface to query (e.g., 'Ethernet').
            If provided, the function returns the default gateway specific
            to that interface. If ``None`` (default), it returns the
            system-wide primary default gateway based on the lowest route
            metric.

    Returns:
        str: The IP address of the default gateway.

    Raises:
        CommandExecutionError: If no default gateway is found.

    CLI Example:

    .. code-block:: bash

        # Get the system's primary default gateway
        salt 'minion' ip.get_default_gateway

        # Get the gateway for a specific interface
        salt 'minion' ip.get_default_gateway iface='Local Area Connection'
    zl
                Get-NetRoute -DestinationPrefix '0.0.0.0/0' `
                             -InterfaceIndex z� `
                             -ErrorAction SilentlyContinue |
                    Sort-Object RouteMetric |
                    Select-Object -First 1 -ExpandProperty NextHop
            z�
                Get-NetRoute -DestinationPrefix '0.0.0.0/0' `
                             -ErrorAction SilentlyContinue |
                    Sort-Object RouteMetric |
                    Select-Object -First 1 -ExpandProperty NextHop
            NzUnable to find default gatewayr�)r?rNrjr:rhr
r
r�get_default_gatewayvs
��r�cshd��d��d����fdd�}|dur||�Stjj���}||�Wd�S1s-wYdS)ah
    Return the integer ``ifIndex`` for the named interface.

    Args:

        iface (str):
            The interface name or alias (e.g., ``'Ethernet'``).

        session (:class:`~salt.utils.win_pwsh.PowerShellSession`, optional):
            An existing ``PowerShellSession`` to reuse. If ``None`` (default),
            a new session is opened for this call only.

    Returns:
        int: The interface index.

    Raises:
        CommandExecutionError: If the interface cannot be found.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.get_interface_index 'Ethernet'
    z*
        $adapter = Get-NetAdapter -Name "z�" `
                                  -ErrorAction SilentlyContinue
        if (-not $adapter) {
            $adapter = Get-NetIPInterface -InterfaceAlias "z�" `
                                          -ErrorAction SilentlyContinue |
                Select-Object -First 1
        }
        if ($adapter) { $adapter.ifIndex } else { "0" }
    c	sR|���}zt|�}Wnttfytd�����w|dkr'td�����|S)Nz(Interface not found or not initialized: rzInterface not found: )rIrJrKrLr)�sZ	raw_indexrj�r:r?r
r�_run�s
��z!get_interface_index.<locals>._runN)rrrrH)r?rNr�r�r
r�rre�s��$�rec6Cs�|r|��dvrtd|����|dur|dks|dkrtd��t|t�r&|n|r+|gng}t|
t�r4|
n|
r9|
gng}t|�}t�d|�d��}|dur]|rPd	nd
}|t�d|�d��7}|durw|t�d
|�d��7}|t�d|�d��7}d||||	fd||||ffD]�\}}}}} |dur�|dkr�dnd}!|r�dnd}|t�d|�d|!�d��7}tdd�||| fD���rd|��}"|dur�|"d|r�dnd��7}"|dur�|"d |r�dnd��7}"| dur�| d!kr�|"d"7}"n|"d#| ��7}"|t�d$|"���7}|�r|t�d%|�d&��7}q�d||fd||ffD]N\}}#}|#�r`|�s`|�s,|t�d'|�d(��7}|#D]1}$|$�d)�}%|%d!}&t	|%�d*k�rD|%d*n|dk�rKd+nd,}'|t�d-|&�d.|'�d/|�d$��7}�q.�qd||	fd||ffD]f\}}(})|(du�r�|dk�r}d0nd1}*|t�d2|*�d3��7}t|(t��r�|(n|(g}+|+D]9},t|,t
��r�|,�d4�|,�d5|)�r�|)nd!�}&}-n
|,|)�r�|)nd!}&}-|&�r�|t�d6|*�d7|&�d8|-�d9��7}�q��ql|�r�|t�d:|�d&��7}|du�r�|t�d;|�r�d<nd=���7}d|fd|ffD]=\}}.|.du�r9|.�s|t�d>|�d?��7}�q�t|.t��r|.n|.g}/d@dA�dBdC�|/D��dD}0|t�dE|0���7}�q�|
du�rtt|
t��rH|
n|
g}1t	|1�d!k�rV|1d!ndFt	|1�d*k�rb|1d*ndF}2}3|t�dG|2�dH|3�dI��7}|�r�d!d*dJd�|��}4|t�dK|4���7}|�r�||k�r�|t�dL|�dM��7}|t�dN�7}t
jj���}5|5�gdO��|5�|�Wd�dPS1�s�wYdPS)Qa�
    Configures a network interface on Windows.

    This function provides a context-aware interface for managing adapter
    properties, protocol bindings, and IP configurations. It utilizes the
    InterfaceIndex to ensure stability during renames.

    **Understanding Metrics on Windows:**
    Windows calculates route priority by summing the **Interface Metric**
    (protocol level) and the **Route Metric** (gateway level).

    * **Interface Metric:** Set via ``ipvX_metric``. A value of ``0``
      enables 'Automatic Metric', where Windows assigns priority based on link
      speed.
    * **Route Metric:** Set within the ``ipvX_gateways`` objects.
    * **Total Cost:** Interface Metric + Route Metric. The lowest total
      cost determines the primary route.

    **Context-Aware Behavior:**
    The function identifies the current state of protocol bindings (IPv4/IPv6)
    before applying settings.

    * If a protocol is disabled and ``ipvX_enabled`` is not passed as ``True``,
      configuration for that stack (IPs, DNS, etc.) is skipped to prevent
      errors.
    * If ``ipvX_dhcp`` is enabled, static IP and gateway configurations are
      ignored by the OS; therefore, this function skips applying static
      addresses unless DHCP is ``False``.

    Args:

        iface (str):
            The current name or alias of the interface (e.g., 'Ethernet').

        alias (str, optional):
            A new name for the interface.

        enabled (bool, optional):
            Administrative status of the adapter.

        ipv4_enabled (bool, optional):
            Whether the IPv4 protocol is bound to this adapter. If ``None``, the
            function discovers current state.

        ipv4_address (list, optional):
            An IPv4 address or list of addresses in CIDR notation
            (e.g., ``['192.168.1.5/24']``).

            .. note::
                If a CIDR prefix is not provided, it will default to ``/24``.

        ipv4_dhcp (bool, optional):
            Set to ``True`` to enable DHCP, ``False`` for static.

        ipv4_dns (list, optional):
            A list of IPv4 DNS server addresses. Passing an empty list ``[]``
            resets DNS to automatic.

        ipv4_forwarding (bool, optional):
            Enables or disables **IP Forwarding** for the IPv4 stack. When
            ``True``, this allows the Windows machine to act as a router,
            passing traffic between this interface and others.
            Default is ``None`` (no change).

        ipv4_gateways (list, str, dict):
            The default gateway(s). Accepts multiple formats:

            * **String:** A single IP address (e.g., ``'192.168.1.1'``).
            * **List of Strings:** Multiple gateways (e.g., ``['1.1.1.1', '1.0.0.1']``).
            * **Dictionary:** A single gateway with a specific route metric
              (e.g., ``{'ip': '192.168.1.1', 'metric': 5}``).
            * **List of Dictionaries:** Multiple gateways with individual metrics
              (e.g., ``[{'ip': '1.1.1.1', 'metric': 2}, {'ip': '1.0.0.1', 'metric': 10}]``).

            If a metric is not specified within a dictionary, or if a string/list
            of strings is provided, the function falls back to ``ipv4_metric``.

        ipv4_metric (int, optional):
            The IPv4 interface metric. Use ``0`` for Automatic.

        ipv4_wins (list, optional):
            A list of up to two WINS server addresses.

        ipv4_netbios (str, optional):
            Configures NetBIOS over TCP/IP behavior via the MSFT_NetIPInterface
            CIM class.

            * ``Default`` (0): Defer to DHCP server settings.
            * ``Enable`` (1): Explicitly enable NetBIOS.
            * ``Disable`` (2): Explicitly disable NetBIOS.

        ipv6_enabled (bool, optional):
            Whether the IPv6 protocol is bound.

        ipv6_address (list, optional):
            An IPv6 address or list of addresses in CIDR notation
            (e.g., ``['2001:db8::1/64']``).

            .. note::
                If a CIDR prefix is not provided, it will default to ``/64``.

        ipv6_dhcp (bool, optional):
            Set to ``True`` for IPv6 stateful configuration.

        ipv6_dns (list, optional):
            A list of IPv6 DNS server addresses.

        ipv6_forwarding (bool, optional):
            Enables or disables **IP Forwarding** for the IPv6 stack. When
            ``True``, this allows the Windows machine to act as a router,
            passing traffic between this interface and others.
            Default is ``None`` (no change).

        ipv6_gateways (list, optional):
            The default gateway(s) for IPv6. Accepts multiple formats:

            * **String:** A single IPv6 address (e.g., ``'2001:db8::1'``).
            * **List of Strings:** Multiple gateways (e.g., ``['2001:db8::1', 'fe80::1']``).
            * **Dictionary:** A single gateway with a specific route metric
              (e.g., ``{'ip': '2001:db8::1', 'metric': 5}``).
            * **List of Dictionaries:** Multiple gateways with individual metrics
              (e.g., ``[{'ip': '2001:db8::1', 'metric': 2}, {'ip': 'fe80::1', 'metric': 10}]``).

            If a metric is not specified within a dictionary, or if a string/list
            of strings is provided, the function falls back to ``ipv6_metric``.
            Note that link-local gateways (starting with ``fe80::``) are fully
            supported as Windows scopes them via the interface index.

        ipv6_metric (int, optional):
            The IPv6 interface metric. Use ``0`` for Automatic.

        dns_register (bool, optional):
            Controls whether the interface's IP addresses are registered in DNS
            using the computer's primary DNS suffix.

            * ``True`` (Default in Windows): Corresponds to "Primary only" in
              legacy output. The computer will attempt to dynamically update
              its DNS record (A/AAAA) on the DNS server.
            * ``False``: Corresponds to "None". The computer will not attempt
              to register its name for this specific connection.

        dns_suffix (str, optional):
            Sets the **Connection-Specific DNS Suffix** (e.g.,
            ``corp.example.com``). This value is used in DNS registration and
            resolution but does not change the global primary DNS suffix of the
            computer.

        mtu (int, optional):
            Configures the **Maximum Transmission Unit** size for the physical
            adapter. Accepts values between ``576`` and ``9000``. Common uses
            include setting ``9000`` for Jumbo Frames in iSCSI/Storage networks
            or lower values for VPN compatibility.

        append (bool):
            If ``True``, the provided IPv4 and IPv6 addresses will be added
            to the interface without removing existing ones. If ``False`` (default),
            all existing IPv4/IPv6 addresses on the interface will be removed
            before applying the new configuration.

            .. note::
                This flag only applies to IP addresses. Gateways (Default Routes)
                are always replaced if a new gateway is provided to ensure
                routing stability.

    Returns:
        bool: ``True`` if successful, otherwise raises an exception.

    CLI Examples:

    .. code-block:: bash

        # Set static IPv4 with a specific metric
        salt-call --local win_ip.set_interface "Ethernet" ipv4_dhcp=False \
            ipv4_address="['192.168.1.10/24']" ipv4_metric=10

        # Set multiple gateways with different route priorities
        salt-call --local win_ip.set_interface "Test-Iface" \
            ipv4_gateways="[{'ip': '10.0.0.1', 'metric': 2}, {'ip': '10.0.0.2', 'metric': 100}]"

        # Reset DNS to automatic/DHCP
        salt '*' win_ip.set_interface "Wi-Fi" ipv4_dns="[]"

        # Rename an interface and enable IPv6
        salt-call --local win_ip.set_interface "Ethernet 2" alias="Production" \
            ipv6_enabled=True ipv6_dhcp=True
    )�defaultrZr\zInvalid NetBIOS setting: Ni@i(#z!MTU must be between 576 and 9000.�
        $idx = a�
        $ErrorActionPreference = 'Stop'
        # Internal Sanitizer for DHCP transitions
        function Sanitize-Stack {
            param([int]$i, [string]$family)
            $stack = if($family -eq 'IPv4') { 'Tcpip' } else { 'Tcpip6' }
            $guid = (Get-NetAdapter -InterfaceIndex $i).DeviceGuid
            $reg = "HKLM:\\SYSTEM\\CurrentControlSet\\Services\\$stack\\Parameters\\Interfaces\\$guid"
            if (Test-Path $reg) {
                Set-ItemProperty $reg 'NameServer' '' -ErrorAction SilentlyContinue
                Set-ItemProperty $reg 'DefaultGateway' ([string[]]@()) -ErrorAction SilentlyContinue
                if ($family -eq 'IPv4') {
                    Set-ItemProperty $reg 'WINSPrimaryServer' '' -ErrorAction SilentlyContinue
                    Set-ItemProperty $reg 'WINSSecondaryServer' '' -ErrorAction SilentlyContinue
                    $bt = "HKLM:\\SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\\TcpIp_$guid"
                    if (Test-Path $bt) { Set-ItemProperty $bt 'NameServerList' ([string[]]@()) -ErrorAction SilentlyContinue }
                    # THE NUCLEAR ADDITION: Flush the WMI Cache specifically
                    $wmi = Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "InterfaceIndex = $i" -ErrorAction SilentlyContinue
                    if ($wmi) {
                        $wmi | Invoke-CimMethod -MethodName SetWINSServer -Arguments @{WINSPrimaryServer=''; WINSSecondaryServer=''} -ErrorAction SilentlyContinue
                    }
                }
            }
            $prefix = if($family -eq 'IPv4') { '0.0.0.0/0' } else { '::/0' }
            $r = try { Get-NetRoute -InterfaceIndex $idx -DestinationPrefix $prefix -ErrorAction SilentlyContinue } catch { $null }
            if ($r) { try { $r | Remove-NetRoute -Confirm:$false } catch { } }
            $a = try { Get-NetIPAddress -InterfaceIndex $idx -AddressFamily $family -ErrorAction SilentlyContinue | Where-Object { $_.PrefixOrigin -eq 'Manual' } } catch { $null }
            if ($a) { try { $a | Remove-NetIPAddress -Confirm:$false } catch { } }
            Set-DnsClientServerAddress -InterfaceIndex $idx -ResetServerAddresses -ErrorAction SilentlyContinue
        }
    zEnable-NetAdapterzDisable-NetAdapterz3
            Get-NetAdapter -InterfaceIndex $idx | z -Confirm:$falsez�
            Set-NetIPInterface -InterfaceIndex $idx `
                               -AddressFamily IPv4 `
                               -NlMtuBytes z1 `
                               -Confirm:$falsez�
            Set-NetIPInterface -InterfaceIndex $idx `
                               -AddressFamily IPv6 `
                               -NlMtuBytes zp `
                               -Confirm:$false `
                               -ErrorAction SilentlyContinueZIPv4ZIPv6Zms_tcpipZ	ms_tcpip6zEnable-NetAdapterBindingzDisable-NetAdapterBindingz7
                Get-NetAdapter -InterfaceIndex $idx | z -ComponentID 'z' -ErrorAction SilentlyContinuecss�|]}|duVqdS�Nr
)r$�xr
r
r�	<genexpr>s�z set_interface.<locals>.<genexpr>z7Set-NetIPInterface -InterfaceIndex $idx -AddressFamily z -Dhcp ZEnabledZDisabledz
 -Forwarding rz -AutomaticMetric Enabledz, -AutomaticMetric Disabled -InterfaceMetric z
                z5
                    Sanitize-Stack -i $idx -family 'r]z�
                    $currentIPs = try {
                        Get-NetIPAddress -InterfaceIndex $idx `
                                         -AddressFamily a� `
                                         -ErrorAction SilentlyContinue |
                        Where-Object { $_.IPAddress -notlike 'fe80*' -and $_.PrefixOrigin -eq 'Manual' }
                    } catch { $null }
                    if ($currentIPs) {
                        try { $currentIPs | Remove-NetIPAddress -Confirm:$false } catch { }
                    }
                rbrFrcZ64zn
                    New-NetIPAddress -InterfaceIndex $idx `
                                     -IPAddress 'z7' `
                                     -PrefixLength z7 `
                                     -AddressFamily z	0.0.0.0/0z::/0z�
                $routes = try {
                    Get-NetRoute -InterfaceIndex $idx `
                                 -DestinationPrefix 'z�' `
                                 -ErrorAction SilentlyContinue
                } catch { $null }
                if ($routes) {
                    try { $routes | Remove-NetRoute -Confirm:$false } catch { }
                }rr)zv
                        New-NetRoute -InterfaceIndex $idx `
                                     -DestinationPrefix 'z3' `
                                     -NextHop 'z6' `
                                     -RouteMetric z7 `
                                     -Confirm:$falsezg
            Set-DnsClient -InterfaceIndex $idx `
                          -ConnectionSpecificSuffix 'zl
            Set-DnsClient -InterfaceIndex $idx `
                          -RegisterThisConnectionsAddress z$truez$falsez�
                    Set-DnsClientServerAddress -InterfaceIndex $idx `
                                               -AddressFamily zG `
                                               -ResetServerAddressesz@(r|cSr~rr
)r$r�r
r
rr&�r�z!set_interface.<locals>.<listcomp>�)z�
                    Set-DnsClientServerAddress -InterfaceIndex $idx `
                                               -ServerAddresses �a
            $w = Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "InterfaceIndex = $idx"
            if($w) {
                $w | Invoke-CimMethod -MethodName SetWINSServer `
                                      -Arguments @{WINSPrimaryServer='z'; WINSSecondaryServer='z'}
            }rSz�
            Set-NetIPInterface -InterfaceIndex $idx `
                               -AddressFamily IPv4 `
                               -NetbiosSetting z[
            Get-NetAdapter -InterfaceIndex $idx |
            Rename-NetAdapter -NewName 'z1' `
                              -Confirm:$falseao
    $iface = Get-NetAdapter -InterfaceIndex $idx `
                            -ErrorAction SilentlyContinue
    if ($iface.AdminStatus -eq 1 -and $iface.MediaConnectionState -eq 1) {
        $timeout = [System.Diagnostics.Stopwatch]::StartNew()
        while ($timeout.Elapsed.TotalSeconds -lt 10) {
            # Check for any addresses still in the 'Tentative' state.
            # Wrap in try/catch: Get-NetIPAddress throws a terminating CIM error
            # when the IP stack is disabled, which -ErrorAction cannot suppress.
            $tentative = try {
                Get-NetIPAddress -InterfaceIndex $idx -ErrorAction SilentlyContinue |
                Where-Object { $_.AddressState -eq 'Tentative' }
            } catch { $null }
            if (-not $tentative) {
                break
            }
            Start-Sleep -Milliseconds 200
        }
    }
    �Z
NetAdapterZNetTCPIPZ	DnsClientT)r�rrrfre�textwrap�dedent�anyrd�lenrrr�rrrrH�import_modulesZ
run_strict)6r?�aliasrWZipv4_enabledrrrZipv4_forwardingr
rrZipv4_netbiosZipv6_enabledZipv6_addressZ	ipv6_dhcpZipv6_dnsZipv6_forwardingrZipv6_metricrZ
dns_suffixZmtur0Z
ipv4_addrsZ
ipv6_addrsrjZ	ps_script�action�familyZactiveZdhcpZforwardr)�compr:r�r��partsrZprefZgatewaysZmetric_fallback�prefixZgw_listZgwZmetZdns_serversZs_listZ
dns_array_str�w�pr�Znb_valrNr
r
rrY�svU������$�������
����

��������
&����
���
��
������
��
��
�
����
6���	�����
��rYcCslt|�}d|�d�}tjj���}|�gd��|�|�}Wd�n1s'wY|r2t|�||iS)u�
    Retrieves the current configuration of a network interface on Windows.

    This function gathers comprehensive data about a network adapter, including
    administrative status, protocol bindings, IP addresses, DNS servers,
    gateways, and WINS configuration. The returned dictionary is structured
    to be directly compatible with the parameters of ``set_interface``.

    **Data Structures and Round-trip Logic:**

    * **Addresses:** IPs are returned in CIDR notation (e.g., ``10.0.0.5/24``)
      to ensure the setter can accurately recreate the subnet mask.
    * **Gateways:** Returned as a list of dictionaries containing both the
      IP (``ip``) and the route-specific metric (``metric``).
    * **Metrics:** A value of ``0`` indicates that the interface is
      configured for 'Automatic Metric' calculation by Windows.

    Args:

        iface (str):
            The name or alias of the interface (e.g., 'Ethernet'). This is used
            for the initial hardware lookup to find the permanent ``InterfaceIndex``.

    Returns:
        dict: A dictionary keyed by the interface name containing:

            - **alias** (str): The friendly name of the adapter.
            - **description** (str): Human-readable adapter description
              (e.g., ``"Microsoft Loopback Adapter"``).
            - **enabled** (bool): Administrative status (``True`` = Up).
            - **index** (int): The stable ``InterfaceIndex`` used internally
              by all CIM/PowerShell cmdlets.
            - **link_status** (str): Current link state reported by the driver
              (e.g., ``"Up"``, ``"Disconnected"``).
            - **mac_address** (str): The physical (MAC) address of the adapter.
            - **mtu** (int): MTU in bytes; defaults to ``1500`` when the
              adapter reports no value (``4294967295`` or ``None``).
            - **dns_register** (bool): ``True`` if the adapter registers its
              addresses in DNS using the computer's primary DNS suffix.
            - **dns_suffix** (str): Connection-specific DNS suffix, or
              ``None`` if not set.
            - **ipv4_enabled** (bool): Status of the IPv4 protocol binding.
            - **ipv4_dhcp** (bool): ``True`` if IPv4 DHCP is enabled.
            - **ipv4_metric** (int): The IPv4 interface metric (``0`` = Auto).
            - **ipv4_address** (list): List of IPv4 addresses in CIDR format.
            - **ipv4_gateways** (list): List of dicts, each with ``ip`` and
              ``metric`` keys, for IPv4 default routes. Always a list — even
              when only one gateway is configured — because
              :func:`_normalize_gateway_fields` corrects the PowerShell 5.1
              behavior of unwrapping single-element arrays.
            - **ipv4_dns** (list): List of IPv4 DNS server addresses.
            - **ipv4_forwarding** (bool | None): ``True`` if IPv4 forwarding
              is enabled, ``None`` if the IPv4 stack is not bound.
            - **ipv4_wins** (list): Primary and secondary WINS server
              addresses (empty list if none configured).
            - **ipv4_netbios** (str): NetBIOS configuration —
              ``"Default"``, ``"Enable"``, or ``"Disable"``.
            - **ipv6_enabled** (bool): Status of the IPv6 protocol binding.
            - **ipv6_dhcp** (bool): ``True`` if IPv6 stateful config is
              enabled.
            - **ipv6_metric** (int): The IPv6 interface metric (``0`` = Auto).
            - **ipv6_address** (list): List of IPv6 addresses in CIDR format.
            - **ipv6_gateways** (list): List of dicts, each with ``ip`` and
              ``metric`` keys, for IPv6 default routes. Always a list for the
              same reason as ``ipv4_gateways``.
            - **ipv6_dns** (list): List of IPv6 DNS server addresses.
            - **ipv6_forwarding** (bool | None): ``True`` if IPv6 forwarding
              is enabled, ``None`` if the IPv6 stack is not bound.

    Raises:
        CommandExecutionError: If the specified interface cannot be found.

    CLI Examples:

    .. code-block:: bash

        # Get details for a specific interface
        salt-call --local win_ip.get_interface_new "Ethernet"

        # Get details for the loopback test adapter
        salt '*' win_ip.get_interface_new "Test-Iface"
    r�a�
        $adapter = Get-NetAdapter -InterfaceIndex $idx -ErrorAction SilentlyContinue
        if (-not $adapter) { return @{} | ConvertTo-Json }

        $ipv4 = Get-NetIPInterface -InterfaceIndex $idx -AddressFamily IPv4 -ErrorAction SilentlyContinue
        $ipv6 = Get-NetIPInterface -InterfaceIndex $idx -AddressFamily IPv6 -ErrorAction SilentlyContinue
        $dns  = Get-DnsClientServerAddress -InterfaceIndex $idx -ErrorAction SilentlyContinue
        $reg  = Get-DnsClient -InterfaceIndex $idx -ErrorAction SilentlyContinue
        $wmi  = Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "InterfaceIndex = $idx" -ErrorAction SilentlyContinue

        $rawMtu = if ($ipv4) { $ipv4.NlMtu } elseif ($ipv6) { $ipv6.NlMtu } else { $adapter.MtuSize }
        $finalMtu = if ($rawMtu -eq 4294967295 -or $null -eq $rawMtu) { 1500 } else { $rawMtu }

        # Helper to format IPs into CIDR
        function Get-CIDR {
            param($family)
            $ips = Get-NetIPAddress -InterfaceIndex $idx -AddressFamily $family -ErrorAction SilentlyContinue |
                   Where-Object { $_.AddressState -eq 'Preferred' -and $_.IPAddress -notlike 'fe80*' }
            if ($ips) { @($ips | ForEach-Object { "$($_.IPAddress)/$($_.PrefixLength)" }) } else { @() }
        }

        # Helper to format Gateways
        function Get-Gateways {
            param($family)
            $prefix = if($family -eq 'IPv4') { "0.0.0.0/0" } else { "::/0" }
            $routes = Get-NetRoute -InterfaceIndex $idx -DestinationPrefix $prefix -ErrorAction SilentlyContinue |
                      Where-Object { $_.NextHop -and $_.NextHop -notmatch '^0\.0\.0\.0$|^::$' }
            if ($routes) {
                @($routes | Select-Object @{Name='ip';Expression={$_.NextHop}}, @{Name='metric';Expression={$_.RouteMetric}})
            } else { @() }
        }

        $result = [PSCustomObject]@{
            alias           = $adapter.Name
            description     = $adapter.InterfaceDescription
            dns_register    = $reg.RegisterThisConnectionsAddress
            dns_suffix      = $reg.ConnectionSpecificSuffix
            enabled         = $adapter.AdminStatus -eq 1
            index           = $idx
            link_status     = $adapter.Status
            mac_address     = $adapter.MacAddress
            mtu             = [int]$finalMtu

            # IPv4 Stack
            ipv4_address    = Get-CIDR -family IPv4
            ipv4_dhcp       = if($ipv4) { $ipv4.Dhcp -eq 1 } else { $false }
            ipv4_dns        = @($dns | Where-Object {$_.AddressFamily -eq 2} | Select-Object -ExpandProperty ServerAddresses)
            ipv4_enabled    = $null -ne $ipv4
            ipv4_forwarding = if ($ipv4) { $ipv4.Forwarding -eq 1 } else { $null }
            ipv4_gateways   = Get-Gateways -family IPv4
            ipv4_metric     = if($ipv4) { $ipv4.InterfaceMetric } else { 0 }
            ipv4_netbios    = switch($ipv4.NetbiosSetting) { 1 {"Enable"} 2 {"Disable"} Default {"Default"} }
            ipv4_wins       = @($wmi.WINSPrimaryServer, $wmi.WINSSecondaryServer).Where({$_})

            # IPv6 Stack
            ipv6_address    = Get-CIDR -family IPv6
            ipv6_dhcp       = if($ipv6) { $ipv6.Dhcp -eq 1 } else { $false }
            ipv6_dns        = @($dns | Where-Object {$_.AddressFamily -eq 23} | Select-Object -ExpandProperty ServerAddresses)
            ipv6_enabled    = $null -ne $ipv6
            ipv6_forwarding = if ($ipv6) { $ipv6.Forwarding -eq 1 } else { $null }
            ipv6_gateways   = Get-Gateways -family IPv6
            ipv6_metric     = if($ipv6) { $ipv6.InterfaceMetric } else { 0 }
        }

        $result | ConvertTo-Json -Depth 5 -Compress
        r�N)rerrrrHr�rpr)r?rjr:rNrr
r
rr*�sS�D�r*cCs�tjj���V}|�gd��|s1|�d�}|s gWd�St|t�r'|n|gWd�Sd}|�|�}|sCiWd�S|��D]}t|t	�rRt
|�qG|Wd�S1s_wYdS)u�
    Lists the available network interfaces on the system.

    Args:

        full (bool, optional): If ``True``, returns a dictionary keyed by
            interface names with detailed configuration for each adapter.
            If ``False``, returns a list of interface names only.
            Defaults to ``False``.

    Returns:
        list: When ``full=False``, a list of interface name strings.

        dict: When ``full=True``, a dictionary keyed by interface name.
            Each value has the same structure as the per-interface dict
            returned by :func:`get_interface_new` — see that function for
            the full field reference (``alias``, ``description``, ``enabled``,
            ``index``, ``link_status``, ``mac_address``, ``mtu``,
            ``dns_register``, ``dns_suffix``, ``ipv4_*``, ``ipv6_*``).

            The entire dataset is collected in a **single PowerShell
            invocation** rather than one session per adapter, so it is
            significantly faster than calling :func:`get_interface_new`
            in a loop.

    CLI Example:

    .. code-block:: bash

        salt -G 'os_family:Windows' ip.list_interfaces
        salt -G 'os_family:Windows' ip.list_interfaces full=True
    r�z(Get-NetAdapter).NameNa�
            function Get-CIDR {
                param([int]$idx, [string]$family)
                $ips = Get-NetIPAddress -InterfaceIndex $idx -AddressFamily $family -ErrorAction SilentlyContinue |
                       Where-Object { $_.AddressState -eq 'Preferred' -and $_.IPAddress -notlike 'fe80*' }
                if ($ips) { @($ips | ForEach-Object { "$($_.IPAddress)/$($_.PrefixLength)" }) } else { @() }
            }

            function Get-Gateways {
                param([int]$idx, [string]$family)
                $prefix = if ($family -eq 'IPv4') { "0.0.0.0/0" } else { "::/0" }
                $routes = Get-NetRoute -InterfaceIndex $idx -DestinationPrefix $prefix -ErrorAction SilentlyContinue |
                          Where-Object { $_.NextHop -and $_.NextHop -notmatch '^0\.0\.0\.0$|^::$' }
                if ($routes) {
                    @($routes | Select-Object @{Name='ip';Expression={$_.NextHop}}, @{Name='metric';Expression={$_.RouteMetric}})
                } else { @() }
            }

            $out = @{}
            Get-NetAdapter | ForEach-Object {
                $adapter = $_
                $idx     = [int]$adapter.ifIndex

                $ipv4 = Get-NetIPInterface -InterfaceIndex $idx -AddressFamily IPv4 -ErrorAction SilentlyContinue
                $ipv6 = Get-NetIPInterface -InterfaceIndex $idx -AddressFamily IPv6 -ErrorAction SilentlyContinue
                $dns  = Get-DnsClientServerAddress -InterfaceIndex $idx -ErrorAction SilentlyContinue
                $reg  = Get-DnsClient -InterfaceIndex $idx -ErrorAction SilentlyContinue
                $wmi  = Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "InterfaceIndex = $idx" -ErrorAction SilentlyContinue

                $rawMtu   = if ($ipv4) { $ipv4.NlMtu } elseif ($ipv6) { $ipv6.NlMtu } else { $adapter.MtuSize }
                $finalMtu = if ($rawMtu -eq 4294967295 -or $null -eq $rawMtu) { 1500 } else { $rawMtu }

                $out[$adapter.Name] = [PSCustomObject]@{
                    alias           = $adapter.Name
                    description     = $adapter.InterfaceDescription
                    dns_register    = $reg.RegisterThisConnectionsAddress
                    dns_suffix      = $reg.ConnectionSpecificSuffix
                    enabled         = $adapter.AdminStatus -eq 1
                    index           = $idx
                    link_status     = $adapter.Status
                    mac_address     = $adapter.MacAddress
                    mtu             = [int]$finalMtu

                    ipv4_address    = Get-CIDR -idx $idx -family IPv4
                    ipv4_dhcp       = if ($ipv4) { $ipv4.Dhcp -eq 1 } else { $false }
                    ipv4_dns        = @($dns | Where-Object { $_.AddressFamily -eq 2 } | Select-Object -ExpandProperty ServerAddresses)
                    ipv4_enabled    = $null -ne $ipv4
                    ipv4_forwarding = if ($ipv4) { $ipv4.Forwarding -eq 1 } else { $null }
                    ipv4_gateways   = Get-Gateways -idx $idx -family IPv4
                    ipv4_metric     = if ($ipv4) { $ipv4.InterfaceMetric } else { 0 }
                    ipv4_netbios    = switch ($ipv4.NetbiosSetting) { 1 { "Enable" } 2 { "Disable" } Default { "Default" } }
                    ipv4_wins       = @($wmi.WINSPrimaryServer, $wmi.WINSSecondaryServer).Where({ $_ })

                    ipv6_address    = Get-CIDR -idx $idx -family IPv6
                    ipv6_dhcp       = if ($ipv6) { $ipv6.Dhcp -eq 1 } else { $false }
                    ipv6_dns        = @($dns | Where-Object { $_.AddressFamily -eq 23 } | Select-Object -ExpandProperty ServerAddresses)
                    ipv6_enabled    = $null -ne $ipv6
                    ipv6_forwarding = if ($ipv6) { $ipv6.Forwarding -eq 1 } else { $null }
                    ipv6_gateways   = Get-Gateways -idx $idx -family IPv6
                    ipv6_metric     = if ($ipv6) { $ipv6.InterfaceMetric } else { 0 }
                }
            }
            $out | ConvertTo-Json -Depth 5 -Compress
        )rrrrHr�rprrf�valuesrr)rrNrr:Zadapter_datar
r
rr+�s(!
��
@�N
�$�r+r�)NF)NNNNNNNNNNNNNNNNNNNNNF)F)%�__doc__r.�loggingr�Zsalt.utils.networkrZsalt.utils.platformZsalt.utils.validate.netZsalt.utils.win_pwshZsalt.exceptionsrr�	getLogger�__name__�logr	rrr9r;r=r@rQrTrZr\rarnrqr�r�r�r�rerYr*r+r
r
r
r�<module>st

D##
_7]<

88
�}&